drm/radeon/kms: fix DP detect and EDID fetch for DP bridges
[pandora-kernel.git] / drivers / gpu / drm / radeon / radeon_display.c
index 292f73f..6cc17fb 100644 (file)
@@ -282,7 +282,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
        spin_lock_irqsave(&rdev->ddev->event_lock, flags);
        work = radeon_crtc->unpin_work;
        if (work == NULL ||
-           !radeon_fence_signaled(work->fence)) {
+           (work->fence && !radeon_fence_signaled(work->fence))) {
                spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
                return;
        }
@@ -348,7 +348,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        struct radeon_framebuffer *new_radeon_fb;
        struct drm_gem_object *obj;
        struct radeon_bo *rbo;
-       struct radeon_fence *fence;
        struct radeon_unpin_work *work;
        unsigned long flags;
        u32 tiling_flags, pitch_pixels;
@@ -359,16 +358,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        if (work == NULL)
                return -ENOMEM;
 
-       r = radeon_fence_create(rdev, &fence);
-       if (unlikely(r != 0)) {
-               kfree(work);
-               DRM_ERROR("flip queue: failed to create fence.\n");
-               return -ENOMEM;
-       }
        work->event = event;
        work->rdev = rdev;
        work->crtc_id = radeon_crtc->crtc_id;
-       work->fence = radeon_fence_ref(fence);
        old_radeon_fb = to_radeon_framebuffer(crtc->fb);
        new_radeon_fb = to_radeon_framebuffer(fb);
        /* schedule unpin of the old buffer */
@@ -377,6 +369,10 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        drm_gem_object_reference(obj);
        rbo = gem_to_radeon_bo(obj);
        work->old_rbo = rbo;
+       obj = new_radeon_fb->obj;
+       rbo = gem_to_radeon_bo(obj);
+       if (rbo->tbo.sync_obj)
+               work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
        INIT_WORK(&work->work, radeon_unpin_work_func);
 
        /* We borrow the event spin lock for protecting unpin_work */
@@ -391,9 +387,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        /* pin the new buffer */
-       obj = new_radeon_fb->obj;
-       rbo = gem_to_radeon_bo(obj);
-
        DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
                         work->old_rbo, rbo);
 
@@ -461,37 +454,18 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
                goto pflip_cleanup1;
        }
 
-       /* 32 ought to cover us */
-       r = radeon_ring_lock(rdev, 32);
-       if (r) {
-               DRM_ERROR("failed to lock the ring before flip\n");
-               goto pflip_cleanup2;
-       }
-
-       /* emit the fence */
-       radeon_fence_emit(rdev, fence);
        /* set the proper interrupt */
        radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
-       /* fire the ring */
-       radeon_ring_unlock_commit(rdev);
 
        return 0;
 
-pflip_cleanup2:
-       drm_vblank_put(dev, radeon_crtc->crtc_id);
-
 pflip_cleanup1:
-       r = radeon_bo_reserve(rbo, false);
-       if (unlikely(r != 0)) {
+       if (unlikely(radeon_bo_reserve(rbo, false) != 0)) {
                DRM_ERROR("failed to reserve new rbo in error path\n");
                goto pflip_cleanup;
        }
-       r = radeon_bo_unpin(rbo);
-       if (unlikely(r != 0)) {
-               radeon_bo_unreserve(rbo);
-               r = -EINVAL;
+       if (unlikely(radeon_bo_unpin(rbo) != 0)) {
                DRM_ERROR("failed to unpin new rbo in error path\n");
-               goto pflip_cleanup;
        }
        radeon_bo_unreserve(rbo);
 
@@ -501,7 +475,7 @@ pflip_cleanup:
 unlock_free:
        drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
        spin_unlock_irqrestore(&dev->event_lock, flags);
-       radeon_fence_unref(&fence);
+       radeon_fence_unref(&work->fence);
        kfree(work);
 
        return r;
@@ -733,16 +707,21 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
                radeon_router_select_ddc_port(radeon_connector);
 
        if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
-           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
+           (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
                if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
                     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
-                       radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
-       }
-       if (!radeon_connector->ddc_bus)
-               return -1;
-       if (!radeon_connector->edid) {
-               radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &dig->dp_i2c_bus->adapter);
+               else if (radeon_connector->ddc_bus && !radeon_connector->edid)
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &radeon_connector->ddc_bus->adapter);
+       } else {
+               if (radeon_connector->ddc_bus && !radeon_connector->edid)
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &radeon_connector->ddc_bus->adapter);
        }
 
        if (!radeon_connector->edid) {
@@ -777,8 +756,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
        if (!radeon_connector->ddc_bus)
                return -1;
        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+       /* Log EDID retrieval status here. In particular with regard to
+        * connectors with requires_extended_probe flag set, that will prevent
+        * function radeon_dvi_detect() to fetch EDID on this connector,
+        * as long as there is no valid EDID header found */
        if (edid) {
+               DRM_INFO("Radeon display connector %s: Found valid EDID",
+                               drm_get_connector_name(connector));
                kfree(edid);
+       } else {
+               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+                               drm_get_connector_name(connector));
        }
        return ret;
 }