Merge branch 'hwmod_dss_fixes_3.2rc' of git://git.pwsan.com/linux-2.6 into fixes-dss
[pandora-kernel.git] / drivers / gpu / drm / vmwgfx / vmwgfx_kms.c
index 667437b..880e285 100644 (file)
@@ -105,12 +105,17 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
        struct vmw_dma_buffer *dmabuf = NULL;
        int ret;
 
+       /* A lot of the code assumes this */
+       if (handle && (width != 64 || height != 64))
+               return -EINVAL;
+
        if (handle) {
                ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
                                                     handle, &surface);
                if (!ret) {
                        if (!surface->snooper.image) {
                                DRM_ERROR("surface not suitable for cursor\n");
+                               vmw_surface_unreference(&surface);
                                return -EINVAL;
                        }
                } else {
@@ -215,7 +220,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
                SVGA3dCmdHeader header;
                SVGA3dCmdSurfaceDMA dma;
        } *cmd;
-       int ret;
+       int i, ret;
 
        cmd = container_of(header, struct vmw_dma_cmd, header);
 
@@ -237,16 +242,19 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
        box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
                        sizeof(SVGA3dCopyBox);
 
-       if (cmd->dma.guest.pitch != (64 * 4) ||
-           cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+       if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
            box->x != 0    || box->y != 0    || box->z != 0    ||
            box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
-           box->w != 64   || box->h != 64   || box->d != 1    ||
-           box_count != 1) {
+           box->d != 1    || box_count != 1) {
                /* TODO handle none page aligned offsets */
-               /* TODO handle partial uploads and pitch != 256 */
-               /* TODO handle more then one copy (size != 64) */
-               DRM_ERROR("lazy programmer, can't handle weird stuff\n");
+               /* TODO handle more dst & src != 0 */
+               /* TODO handle more then one copy */
+               DRM_ERROR("Cant snoop dma request for cursor!\n");
+               DRM_ERROR("(%u, %u, %u) (%u, %u, %u) (%ux%ux%u) %u %u\n",
+                         box->srcx, box->srcy, box->srcz,
+                         box->x, box->y, box->z,
+                         box->w, box->h, box->d, box_count,
+                         cmd->dma.guest.ptr.offset);
                return;
        }
 
@@ -265,7 +273,16 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
 
        virtual = ttm_kmap_obj_virtual(&map, &dummy);
 
-       memcpy(srf->snooper.image, virtual, 64*64*4);
+       if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
+               memcpy(srf->snooper.image, virtual, 64*64*4);
+       } else {
+               /* Image is unsigned pointer. */
+               for (i = 0; i < box->h; i++)
+                       memcpy(srf->snooper.image + i * 64,
+                              virtual + i * cmd->dma.guest.pitch,
+                              box->w * 4);
+       }
+
        srf->snooper.age++;
 
        /* we can't call this function from this function since execbuf has
@@ -397,8 +414,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
        top = clips->y1;
        bottom = clips->y2;
 
-       clips_ptr = clips;
-       for (i = 1; i < num_clips; i++, clips_ptr += inc) {
+       /* skip the first clip rect */
+       for (i = 1, clips_ptr = clips + inc;
+            i < num_clips; i++, clips_ptr += inc) {
                left = min_t(int, left, (int)clips_ptr->x1);
                right = max_t(int, right, (int)clips_ptr->x2);
                top = min_t(int, top, (int)clips_ptr->y1);
@@ -1310,7 +1328,10 @@ int vmw_kms_close(struct vmw_private *dev_priv)
         * drm_encoder_cleanup which takes the lock we deadlock.
         */
        drm_mode_config_cleanup(dev_priv->dev);
-       vmw_kms_close_legacy_display_system(dev_priv);
+       if (dev_priv->sou_priv)
+               vmw_kms_close_screen_object_display(dev_priv);
+       else
+               vmw_kms_close_legacy_display_system(dev_priv);
        return 0;
 }
 
@@ -1746,6 +1767,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                drm_mode_probed_add(connector, mode);
        }
 
+       /* Move the prefered mode first, help apps pick the right mode. */
+       if (du->pref_mode)
+               list_move(&du->pref_mode->head, &connector->probed_modes);
+
        drm_mode_connector_list_update(connector);
 
        return 1;