]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'v3.2-rc6' of /home/airlied/devel/kernel/linux-2.6 into drm-core-next
authorDave Airlie <airlied@redhat.com>
Tue, 20 Dec 2011 14:43:53 +0000 (14:43 +0000)
committerDave Airlie <airlied@redhat.com>
Tue, 20 Dec 2011 14:43:53 +0000 (14:43 +0000)
Merge in the upstream tree to bring in the mainline fixes.

Conflicts:
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c

26 files changed:
1  2 
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/xen/swiotlb-xen.c
include/drm/drmP.h
include/drm/drm_mode.h

diff --combined drivers/gpu/drm/Kconfig
index 45079046b6d5c6c41f31a2fca3b5860b9e19ba68,1368826ef28475c0f191510b7016dd1068b55187..2418429a98360fd996888e5ccce6189bad9d9a86
@@@ -9,7 -9,6 +9,6 @@@ menuconfig DR
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
        select I2C
        select I2C_ALGOBIT
-       select SLOW_WORK
        help
          Kernel-level support for the Direct Rendering Infrastructure (DRI)
          introduced in XFree86 4.0. If you say Y here, you need to select
@@@ -96,6 -95,7 +95,7 @@@ config DRM_I91
        select FB_CFB_IMAGEBLIT
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+       select BACKLIGHT_LCD_SUPPORT if ACPI
        select BACKLIGHT_CLASS_DEVICE if ACPI
        select VIDEO_OUTPUT_CONTROL if ACPI
        select INPUT if ACPI
@@@ -162,6 -162,3 +162,6 @@@ config DRM_SAVAG
  source "drivers/gpu/drm/exynos/Kconfig"
  
  source "drivers/gpu/drm/vmwgfx/Kconfig"
 +
 +source "drivers/gpu/drm/gma500/Kconfig"
 +
index 0d1faa72e1ff29ba3ce7810d272533ee2e89f846,8323fc3898401ac957d9a677b947455f5a598b91..f259a256320427acce898aa81efd3ad8270e89ef
@@@ -36,7 -36,6 +36,7 @@@
  #include "drmP.h"
  #include "drm_crtc.h"
  #include "drm_edid.h"
 +#include "drm_fourcc.h"
  
  struct drm_prop_enum_list {
        int type;
@@@ -325,7 -324,6 +325,7 @@@ void drm_framebuffer_cleanup(struct drm
  {
        struct drm_device *dev = fb->dev;
        struct drm_crtc *crtc;
 +      struct drm_plane *plane;
        struct drm_mode_set set;
        int ret;
  
                }
        }
  
 +      list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 +              if (plane->fb == fb) {
 +                      /* should turn off the crtc */
 +                      ret = plane->funcs->disable_plane(plane);
 +                      if (ret)
 +                              DRM_ERROR("failed to disable plane with busy fb\n");
 +              }
 +      }
 +
        drm_mode_object_put(dev, &fb->base);
        list_del(&fb->head);
        dev->mode_config.num_fb--;
@@@ -551,51 -540,6 +551,51 @@@ void drm_encoder_cleanup(struct drm_enc
  }
  EXPORT_SYMBOL(drm_encoder_cleanup);
  
 +int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 +                 unsigned long possible_crtcs,
 +                 const struct drm_plane_funcs *funcs,
 +                 const uint32_t *formats, uint32_t format_count)
 +{
 +      mutex_lock(&dev->mode_config.mutex);
 +
 +      plane->dev = dev;
 +      drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
 +      plane->funcs = funcs;
 +      plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
 +                                    GFP_KERNEL);
 +      if (!plane->format_types) {
 +              DRM_DEBUG_KMS("out of memory when allocating plane\n");
 +              drm_mode_object_put(dev, &plane->base);
 +              mutex_unlock(&dev->mode_config.mutex);
 +              return -ENOMEM;
 +      }
 +
 +      memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
 +      plane->format_count = format_count;
 +      plane->possible_crtcs = possible_crtcs;
 +
 +      list_add_tail(&plane->head, &dev->mode_config.plane_list);
 +      dev->mode_config.num_plane++;
 +
 +      mutex_unlock(&dev->mode_config.mutex);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(drm_plane_init);
 +
 +void drm_plane_cleanup(struct drm_plane *plane)
 +{
 +      struct drm_device *dev = plane->dev;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +      kfree(plane->format_types);
 +      drm_mode_object_put(dev, &plane->base);
 +      list_del(&plane->head);
 +      dev->mode_config.num_plane--;
 +      mutex_unlock(&dev->mode_config.mutex);
 +}
 +EXPORT_SYMBOL(drm_plane_cleanup);
 +
  /**
   * drm_mode_create - create a new display mode
   * @dev: DRM device
@@@ -927,7 -871,6 +927,7 @@@ void drm_mode_config_init(struct drm_de
        INIT_LIST_HEAD(&dev->mode_config.encoder_list);
        INIT_LIST_HEAD(&dev->mode_config.property_list);
        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
 +      INIT_LIST_HEAD(&dev->mode_config.plane_list);
        idr_init(&dev->mode_config.crtc_idr);
  
        mutex_lock(&dev->mode_config.mutex);
@@@ -1004,7 -947,6 +1004,7 @@@ void drm_mode_config_cleanup(struct drm
        struct drm_encoder *encoder, *enct;
        struct drm_framebuffer *fb, *fbt;
        struct drm_property *property, *pt;
 +      struct drm_plane *plane, *plt;
  
        list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
                                 head) {
                crtc->funcs->destroy(crtc);
        }
  
 +      list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
 +                               head) {
 +              plane->funcs->destroy(plane);
 +      }
  }
  EXPORT_SYMBOL(drm_mode_config_cleanup);
  
@@@ -1441,7 -1379,7 +1441,7 @@@ int drm_mode_getconnector(struct drm_de
         */
        if ((out_resp->count_modes >= mode_count) && mode_count) {
                copied = 0;
 -              mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr;
 +              mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
                list_for_each_entry(mode, &connector->modes, head) {
                        drm_crtc_convert_to_umode(&u_mode, mode);
                        if (copy_to_user(mode_ptr + copied,
  
        if ((out_resp->count_props >= props_count) && props_count) {
                copied = 0;
 -              prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr);
 -              prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr);
 +              prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
 +              prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
                for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
                        if (connector->property_ids[i] != 0) {
                                if (put_user(connector->property_ids[i],
  
        if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
                copied = 0;
 -              encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr);
 +              encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
                for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
                        if (connector->encoder_ids[i] != 0) {
                                if (put_user(connector->encoder_ids[i],
        return ret;
  }
  
 +/**
 + * drm_mode_getplane_res - get plane info
 + * @dev: DRM device
 + * @data: ioctl data
 + * @file_priv: DRM file info
 + *
 + * Return an plane count and set of IDs.
 + */
 +int drm_mode_getplane_res(struct drm_device *dev, void *data,
 +                          struct drm_file *file_priv)
 +{
 +      struct drm_mode_get_plane_res *plane_resp = data;
 +      struct drm_mode_config *config;
 +      struct drm_plane *plane;
 +      uint32_t __user *plane_ptr;
 +      int copied = 0, ret = 0;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 +              return -EINVAL;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +      config = &dev->mode_config;
 +
 +      /*
 +       * This ioctl is called twice, once to determine how much space is
 +       * needed, and the 2nd time to fill it.
 +       */
 +      if (config->num_plane &&
 +          (plane_resp->count_planes >= config->num_plane)) {
 +              plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
 +
 +              list_for_each_entry(plane, &config->plane_list, head) {
 +                      if (put_user(plane->base.id, plane_ptr + copied)) {
 +                              ret = -EFAULT;
 +                              goto out;
 +                      }
 +                      copied++;
 +              }
 +      }
 +      plane_resp->count_planes = config->num_plane;
 +
 +out:
 +      mutex_unlock(&dev->mode_config.mutex);
 +      return ret;
 +}
 +
 +/**
 + * drm_mode_getplane - get plane info
 + * @dev: DRM device
 + * @data: ioctl data
 + * @file_priv: DRM file info
 + *
 + * Return plane info, including formats supported, gamma size, any
 + * current fb, etc.
 + */
 +int drm_mode_getplane(struct drm_device *dev, void *data,
 +                      struct drm_file *file_priv)
 +{
 +      struct drm_mode_get_plane *plane_resp = data;
 +      struct drm_mode_object *obj;
 +      struct drm_plane *plane;
 +      uint32_t __user *format_ptr;
 +      int ret = 0;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 +              return -EINVAL;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +      obj = drm_mode_object_find(dev, plane_resp->plane_id,
 +                                 DRM_MODE_OBJECT_PLANE);
 +      if (!obj) {
 +              ret = -ENOENT;
 +              goto out;
 +      }
 +      plane = obj_to_plane(obj);
 +
 +      if (plane->crtc)
 +              plane_resp->crtc_id = plane->crtc->base.id;
 +      else
 +              plane_resp->crtc_id = 0;
 +
 +      if (plane->fb)
 +              plane_resp->fb_id = plane->fb->base.id;
 +      else
 +              plane_resp->fb_id = 0;
 +
 +      plane_resp->plane_id = plane->base.id;
 +      plane_resp->possible_crtcs = plane->possible_crtcs;
 +      plane_resp->gamma_size = plane->gamma_size;
 +
 +      /*
 +       * This ioctl is called twice, once to determine how much space is
 +       * needed, and the 2nd time to fill it.
 +       */
 +      if (plane->format_count &&
 +          (plane_resp->count_format_types >= plane->format_count)) {
 +              format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
 +              if (copy_to_user(format_ptr,
 +                               plane->format_types,
 +                               sizeof(uint32_t) * plane->format_count)) {
 +                      ret = -EFAULT;
 +                      goto out;
 +              }
 +      }
 +      plane_resp->count_format_types = plane->format_count;
 +
 +out:
 +      mutex_unlock(&dev->mode_config.mutex);
 +      return ret;
 +}
 +
 +/**
 + * drm_mode_setplane - set up or tear down an plane
 + * @dev: DRM device
 + * @data: ioctl data*
 + * @file_prive: DRM file info
 + *
 + * Set plane info, including placement, fb, scaling, and other factors.
 + * Or pass a NULL fb to disable.
 + */
 +int drm_mode_setplane(struct drm_device *dev, void *data,
 +                      struct drm_file *file_priv)
 +{
 +      struct drm_mode_set_plane *plane_req = data;
 +      struct drm_mode_object *obj;
 +      struct drm_plane *plane;
 +      struct drm_crtc *crtc;
 +      struct drm_framebuffer *fb;
 +      int ret = 0;
 +      unsigned int fb_width, fb_height;
 +      int i;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 +              return -EINVAL;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +
 +      /*
 +       * First, find the plane, crtc, and fb objects.  If not available,
 +       * we don't bother to call the driver.
 +       */
 +      obj = drm_mode_object_find(dev, plane_req->plane_id,
 +                                 DRM_MODE_OBJECT_PLANE);
 +      if (!obj) {
 +              DRM_DEBUG_KMS("Unknown plane ID %d\n",
 +                            plane_req->plane_id);
 +              ret = -ENOENT;
 +              goto out;
 +      }
 +      plane = obj_to_plane(obj);
 +
 +      /* No fb means shut it down */
 +      if (!plane_req->fb_id) {
 +              plane->funcs->disable_plane(plane);
 +              plane->crtc = NULL;
 +              plane->fb = NULL;
 +              goto out;
 +      }
 +
 +      obj = drm_mode_object_find(dev, plane_req->crtc_id,
 +                                 DRM_MODE_OBJECT_CRTC);
 +      if (!obj) {
 +              DRM_DEBUG_KMS("Unknown crtc ID %d\n",
 +                            plane_req->crtc_id);
 +              ret = -ENOENT;
 +              goto out;
 +      }
 +      crtc = obj_to_crtc(obj);
 +
 +      obj = drm_mode_object_find(dev, plane_req->fb_id,
 +                                 DRM_MODE_OBJECT_FB);
 +      if (!obj) {
 +              DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
 +                            plane_req->fb_id);
 +              ret = -ENOENT;
 +              goto out;
 +      }
 +      fb = obj_to_fb(obj);
 +
 +      /* Check whether this plane supports the fb pixel format. */
 +      for (i = 0; i < plane->format_count; i++)
 +              if (fb->pixel_format == plane->format_types[i])
 +                      break;
 +      if (i == plane->format_count) {
 +              DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
 +              ret = -EINVAL;
 +              goto out;
 +      }
 +
 +      fb_width = fb->width << 16;
 +      fb_height = fb->height << 16;
 +
 +      /* Make sure source coordinates are inside the fb. */
 +      if (plane_req->src_w > fb_width ||
 +          plane_req->src_x > fb_width - plane_req->src_w ||
 +          plane_req->src_h > fb_height ||
 +          plane_req->src_y > fb_height - plane_req->src_h) {
 +              DRM_DEBUG_KMS("Invalid source coordinates "
 +                            "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
 +                            plane_req->src_w >> 16,
 +                            ((plane_req->src_w & 0xffff) * 15625) >> 10,
 +                            plane_req->src_h >> 16,
 +                            ((plane_req->src_h & 0xffff) * 15625) >> 10,
 +                            plane_req->src_x >> 16,
 +                            ((plane_req->src_x & 0xffff) * 15625) >> 10,
 +                            plane_req->src_y >> 16,
 +                            ((plane_req->src_y & 0xffff) * 15625) >> 10);
 +              ret = -ENOSPC;
 +              goto out;
 +      }
 +
 +      /* Give drivers some help against integer overflows */
 +      if (plane_req->crtc_w > INT_MAX ||
 +          plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
 +          plane_req->crtc_h > INT_MAX ||
 +          plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
 +              DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
 +                            plane_req->crtc_w, plane_req->crtc_h,
 +                            plane_req->crtc_x, plane_req->crtc_y);
 +              ret = -ERANGE;
 +              goto out;
 +      }
 +
 +      ret = plane->funcs->update_plane(plane, crtc, fb,
 +                                       plane_req->crtc_x, plane_req->crtc_y,
 +                                       plane_req->crtc_w, plane_req->crtc_h,
 +                                       plane_req->src_x, plane_req->src_y,
 +                                       plane_req->src_w, plane_req->src_h);
 +      if (!ret) {
 +              plane->crtc = crtc;
 +              plane->fb = fb;
 +      }
 +
 +out:
 +      mutex_unlock(&dev->mode_config.mutex);
 +
 +      return ret;
 +}
 +
  /**
   * drm_mode_setcrtc - set CRTC configuration
   * @inode: inode from the ioctl
@@@ -1877,7 -1576,7 +1877,7 @@@ int drm_mode_setcrtc(struct drm_device 
                }
  
                for (i = 0; i < crtc_req->count_connectors; i++) {
 -                      set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr;
 +                      set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
                        if (get_user(out_id, &set_connectors_ptr[i])) {
                                ret = -EFAULT;
                                goto out;
@@@ -1926,8 -1625,10 +1926,8 @@@ int drm_mode_cursor_ioctl(struct drm_de
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
  
 -      if (!req->flags) {
 -              DRM_ERROR("no operation set\n");
 +      if (!req->flags)
                return -EINVAL;
 -      }
  
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
  
        if (req->flags & DRM_MODE_CURSOR_BO) {
                if (!crtc->funcs->cursor_set) {
 -                      DRM_ERROR("crtc does not support cursor\n");
                        ret = -ENXIO;
                        goto out;
                }
                if (crtc->funcs->cursor_move) {
                        ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
                } else {
 -                      DRM_ERROR("crtc does not support cursor\n");
                        ret = -EFAULT;
                        goto out;
                }
        return ret;
  }
  
 +/* Original addfb only supported RGB formats, so figure out which one */
 +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
 +{
 +      uint32_t fmt;
 +
 +      switch (bpp) {
 +      case 8:
 +              fmt = DRM_FORMAT_RGB332;
 +              break;
 +      case 16:
 +              if (depth == 15)
 +                      fmt = DRM_FORMAT_XRGB1555;
 +              else
 +                      fmt = DRM_FORMAT_RGB565;
 +              break;
 +      case 24:
 +              fmt = DRM_FORMAT_RGB888;
 +              break;
 +      case 32:
 +              if (depth == 24)
 +                      fmt = DRM_FORMAT_XRGB8888;
 +              else if (depth == 30)
 +                      fmt = DRM_FORMAT_XRGB2101010;
 +              else
 +                      fmt = DRM_FORMAT_ARGB8888;
 +              break;
 +      default:
 +              DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
 +              fmt = DRM_FORMAT_XRGB8888;
 +              break;
 +      }
 +
 +      return fmt;
 +}
 +EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 +
  /**
   * drm_mode_addfb - add an FB to the graphics configuration
   * @inode: inode from the ioctl
  int drm_mode_addfb(struct drm_device *dev,
                   void *data, struct drm_file *file_priv)
  {
 -      struct drm_mode_fb_cmd *r = data;
 +      struct drm_mode_fb_cmd *or = data;
 +      struct drm_mode_fb_cmd2 r = {};
 +      struct drm_mode_config *config = &dev->mode_config;
 +      struct drm_framebuffer *fb;
 +      int ret = 0;
 +
 +      /* Use new struct with format internally */
 +      r.fb_id = or->fb_id;
 +      r.width = or->width;
 +      r.height = or->height;
 +      r.pitches[0] = or->pitch;
 +      r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
 +      r.handles[0] = or->handle;
 +
 +      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 +              return -EINVAL;
 +
 +      if ((config->min_width > r.width) || (r.width > config->max_width))
 +              return -EINVAL;
 +
 +      if ((config->min_height > r.height) || (r.height > config->max_height))
 +              return -EINVAL;
 +
 +      mutex_lock(&dev->mode_config.mutex);
 +
 +      /* TODO check buffer is sufficiently large */
 +      /* TODO setup destructor callback */
 +
 +      fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
 +      if (IS_ERR(fb)) {
 +              DRM_ERROR("could not create framebuffer\n");
 +              ret = PTR_ERR(fb);
 +              goto out;
 +      }
 +
 +      or->fb_id = fb->base.id;
 +      list_add(&fb->filp_head, &file_priv->fbs);
 +      DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
 +
 +out:
 +      mutex_unlock(&dev->mode_config.mutex);
 +      return ret;
 +}
 +
 +static int format_check(struct drm_mode_fb_cmd2 *r)
 +{
 +      uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
 +
 +      switch (format) {
 +      case DRM_FORMAT_C8:
 +      case DRM_FORMAT_RGB332:
 +      case DRM_FORMAT_BGR233:
 +      case DRM_FORMAT_XRGB4444:
 +      case DRM_FORMAT_XBGR4444:
 +      case DRM_FORMAT_RGBX4444:
 +      case DRM_FORMAT_BGRX4444:
 +      case DRM_FORMAT_ARGB4444:
 +      case DRM_FORMAT_ABGR4444:
 +      case DRM_FORMAT_RGBA4444:
 +      case DRM_FORMAT_BGRA4444:
 +      case DRM_FORMAT_XRGB1555:
 +      case DRM_FORMAT_XBGR1555:
 +      case DRM_FORMAT_RGBX5551:
 +      case DRM_FORMAT_BGRX5551:
 +      case DRM_FORMAT_ARGB1555:
 +      case DRM_FORMAT_ABGR1555:
 +      case DRM_FORMAT_RGBA5551:
 +      case DRM_FORMAT_BGRA5551:
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_BGR565:
 +      case DRM_FORMAT_RGB888:
 +      case DRM_FORMAT_BGR888:
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_XBGR8888:
 +      case DRM_FORMAT_RGBX8888:
 +      case DRM_FORMAT_BGRX8888:
 +      case DRM_FORMAT_ARGB8888:
 +      case DRM_FORMAT_ABGR8888:
 +      case DRM_FORMAT_RGBA8888:
 +      case DRM_FORMAT_BGRA8888:
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_XBGR2101010:
 +      case DRM_FORMAT_RGBX1010102:
 +      case DRM_FORMAT_BGRX1010102:
 +      case DRM_FORMAT_ARGB2101010:
 +      case DRM_FORMAT_ABGR2101010:
 +      case DRM_FORMAT_RGBA1010102:
 +      case DRM_FORMAT_BGRA1010102:
 +      case DRM_FORMAT_YUYV:
 +      case DRM_FORMAT_YVYU:
 +      case DRM_FORMAT_UYVY:
 +      case DRM_FORMAT_VYUY:
 +      case DRM_FORMAT_AYUV:
 +      case DRM_FORMAT_NV12:
 +      case DRM_FORMAT_NV21:
 +      case DRM_FORMAT_NV16:
 +      case DRM_FORMAT_NV61:
 +      case DRM_FORMAT_YUV410:
 +      case DRM_FORMAT_YVU410:
 +      case DRM_FORMAT_YUV411:
 +      case DRM_FORMAT_YVU411:
 +      case DRM_FORMAT_YUV420:
 +      case DRM_FORMAT_YVU420:
 +      case DRM_FORMAT_YUV422:
 +      case DRM_FORMAT_YVU422:
 +      case DRM_FORMAT_YUV444:
 +      case DRM_FORMAT_YVU444:
 +              return 0;
 +      default:
 +              return -EINVAL;
 +      }
 +}
 +
 +/**
 + * drm_mode_addfb2 - add an FB to the graphics configuration
 + * @inode: inode from the ioctl
 + * @filp: file * from the ioctl
 + * @cmd: cmd from ioctl
 + * @arg: arg from ioctl
 + *
 + * LOCKING:
 + * Takes mode config lock.
 + *
 + * Add a new FB to the specified CRTC, given a user request with format.
 + *
 + * Called by the user via ioctl.
 + *
 + * RETURNS:
 + * Zero on success, errno on failure.
 + */
 +int drm_mode_addfb2(struct drm_device *dev,
 +                  void *data, struct drm_file *file_priv)
 +{
 +      struct drm_mode_fb_cmd2 *r = data;
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_framebuffer *fb;
        int ret = 0;
                return -EINVAL;
  
        if ((config->min_width > r->width) || (r->width > config->max_width)) {
 -              DRM_ERROR("mode new framebuffer width not within limits\n");
 +              DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
 +                        r->width, config->min_width, config->max_width);
                return -EINVAL;
        }
        if ((config->min_height > r->height) || (r->height > config->max_height)) {
 -              DRM_ERROR("mode new framebuffer height not within limits\n");
 +              DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
 +                        r->height, config->min_height, config->max_height);
                return -EINVAL;
        }
  
 -      mutex_lock(&dev->mode_config.mutex);
 +      ret = format_check(r);
 +      if (ret) {
 +              DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format);
 +              return ret;
 +      }
  
 -      /* TODO check buffer is sufficiently large */
 -      /* TODO setup destructor callback */
 +      mutex_lock(&dev->mode_config.mutex);
  
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (IS_ERR(fb)) {
@@@ -2227,6 -1756,7 +2227,6 @@@ int drm_mode_rmfb(struct drm_device *de
        obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
        /* TODO check that we really get a framebuffer back. */
        if (!obj) {
 -              DRM_ERROR("mode invalid framebuffer id\n");
                ret = -EINVAL;
                goto out;
        }
                        found = 1;
  
        if (!found) {
 -              DRM_ERROR("tried to remove a fb that we didn't own\n");
                ret = -EINVAL;
                goto out;
        }
@@@ -2283,6 -1814,7 +2283,6 @@@ int drm_mode_getfb(struct drm_device *d
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
 -              DRM_ERROR("invalid framebuffer id\n");
                ret = -EINVAL;
                goto out;
        }
        r->width = fb->width;
        r->depth = fb->depth;
        r->bpp = fb->bits_per_pixel;
 -      r->pitch = fb->pitch;
 +      r->pitch = fb->pitches[0];
        fb->funcs->create_handle(fb, file_priv, &r->handle);
  
  out:
@@@ -2318,13 -1850,14 +2318,13 @@@ int drm_mode_dirtyfb_ioctl(struct drm_d
        mutex_lock(&dev->mode_config.mutex);
        obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
        if (!obj) {
 -              DRM_ERROR("invalid framebuffer id\n");
                ret = -EINVAL;
                goto out_err1;
        }
        fb = obj_to_fb(obj);
  
        num_clips = r->num_clips;
 -      clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
 +      clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
  
        if (!num_clips != !clips_ptr) {
                ret = -EINVAL;
        }
  
        if (num_clips && clips_ptr) {
+               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+                       ret = -EINVAL;
+                       goto out_err1;
+               }
                clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
                if (!clips) {
                        ret = -ENOMEM;
@@@ -2585,8 -2122,10 +2589,10 @@@ struct drm_property *drm_property_creat
        property->num_values = num_values;
        INIT_LIST_HEAD(&property->enum_blob_list);
  
-       if (name)
+       if (name) {
                strncpy(property->name, name, DRM_PROP_NAME_LEN);
+               property->name[DRM_PROP_NAME_LEN-1] = '\0';
+       }
  
        list_add_tail(&property->head, &dev->mode_config.property_list);
        return property;
@@@ -2714,7 -2253,7 +2720,7 @@@ int drm_mode_getproperty_ioctl(struct d
        struct drm_property_enum *prop_enum;
        struct drm_mode_property_enum __user *enum_ptr;
        struct drm_property_blob *prop_blob;
 -      uint32_t *blob_id_ptr;
 +      uint32_t __user *blob_id_ptr;
        uint64_t __user *values_ptr;
        uint32_t __user *blob_length_ptr;
  
        out_resp->flags = property->flags;
  
        if ((out_resp->count_values >= value_count) && value_count) {
 -              values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr;
 +              values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
                for (i = 0; i < value_count; i++) {
                        if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
                                ret = -EFAULT;
        if (property->flags & DRM_MODE_PROP_ENUM) {
                if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
                        copied = 0;
 -                      enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
 +                      enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
                        list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
  
                                if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
        if (property->flags & DRM_MODE_PROP_BLOB) {
                if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
                        copied = 0;
 -                      blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr;
 -                      blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr;
 +                      blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
 +                      blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
  
                        list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
                                if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
@@@ -2841,7 -2380,7 +2847,7 @@@ int drm_mode_getblob_ioctl(struct drm_d
        struct drm_mode_get_blob *out_resp = data;
        struct drm_property_blob *blob;
        int ret = 0;
 -      void *blob_ptr;
 +      void __user *blob_ptr;
  
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
        blob = obj_to_blob(obj);
  
        if (out_resp->length == blob->length) {
 -              blob_ptr = (void *)(unsigned long)out_resp->data;
 +              blob_ptr = (void __user *)(unsigned long)out_resp->data;
                if (copy_to_user(blob_ptr, blob->data, blob->length)){
                        ret = -EFAULT;
                        goto done;
@@@ -3249,71 -2788,3 +3255,71 @@@ int drm_mode_destroy_dumb_ioctl(struct 
  
        return dev->driver->dumb_destroy(file_priv, dev, args->handle);
  }
 +
 +/*
 + * Just need to support RGB formats here for compat with code that doesn't
 + * use pixel formats directly yet.
 + */
 +void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
 +                        int *bpp)
 +{
 +      switch (format) {
 +      case DRM_FORMAT_RGB332:
 +      case DRM_FORMAT_BGR233:
 +              *depth = 8;
 +              *bpp = 8;
 +              break;
 +      case DRM_FORMAT_XRGB1555:
 +      case DRM_FORMAT_XBGR1555:
 +      case DRM_FORMAT_RGBX5551:
 +      case DRM_FORMAT_BGRX5551:
 +      case DRM_FORMAT_ARGB1555:
 +      case DRM_FORMAT_ABGR1555:
 +      case DRM_FORMAT_RGBA5551:
 +      case DRM_FORMAT_BGRA5551:
 +              *depth = 15;
 +              *bpp = 16;
 +              break;
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_BGR565:
 +              *depth = 16;
 +              *bpp = 16;
 +              break;
 +      case DRM_FORMAT_RGB888:
 +      case DRM_FORMAT_BGR888:
 +              *depth = 24;
 +              *bpp = 24;
 +              break;
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_XBGR8888:
 +      case DRM_FORMAT_RGBX8888:
 +      case DRM_FORMAT_BGRX8888:
 +              *depth = 24;
 +              *bpp = 32;
 +              break;
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_XBGR2101010:
 +      case DRM_FORMAT_RGBX1010102:
 +      case DRM_FORMAT_BGRX1010102:
 +      case DRM_FORMAT_ARGB2101010:
 +      case DRM_FORMAT_ABGR2101010:
 +      case DRM_FORMAT_RGBA1010102:
 +      case DRM_FORMAT_BGRA1010102:
 +              *depth = 30;
 +              *bpp = 32;
 +              break;
 +      case DRM_FORMAT_ARGB8888:
 +      case DRM_FORMAT_ABGR8888:
 +      case DRM_FORMAT_RGBA8888:
 +      case DRM_FORMAT_BGRA8888:
 +              *depth = 32;
 +              *bpp = 32;
 +              break;
 +      default:
 +              DRM_DEBUG_KMS("unsupported pixel format\n");
 +              *depth = 0;
 +              *bpp = 0;
 +              break;
 +      }
 +}
 +EXPORT_SYMBOL(drm_fb_get_bpp_depth);
index ccbdc0b5854c357772846bae4a3939299dfb2c08,d2619d72ceceb16d7b88a33b09708219483019b4..42f86e71479a13cf2b67f906694e62fa751a57b2
@@@ -34,7 -34,6 +34,7 @@@
  
  #include "drmP.h"
  #include "drm_crtc.h"
 +#include "drm_fourcc.h"
  #include "drm_crtc_helper.h"
  #include "drm_fb_helper.h"
  
@@@ -457,6 -456,30 +457,30 @@@ done
  EXPORT_SYMBOL(drm_crtc_helper_set_mode);
  
  
+ static int
+ drm_crtc_helper_disable(struct drm_crtc *crtc)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       /* Decouple all encoders and their attached connectors from this crtc */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               if (encoder->crtc != crtc)
+                       continue;
+               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+                       if (connector->encoder != encoder)
+                               continue;
+                       connector->encoder = NULL;
+               }
+       }
+       drm_helper_disable_unused_functions(dev);
+       return 0;
+ }
  /**
   * drm_crtc_helper_set_config - set a new config from userspace
   * @crtc: CRTC to setup
@@@ -485,6 -508,7 +509,7 @@@ int drm_crtc_helper_set_config(struct d
        struct drm_connector *save_connectors, *connector;
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_mode_set save_set;
        int ret = 0;
        int i;
  
                                (int)set->num_connectors, set->x, set->y);
        } else {
                DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-               set->mode = NULL;
-               set->num_connectors = 0;
+               return drm_crtc_helper_disable(set->crtc);
        }
  
        dev = set->crtc->dev;
                save_connectors[count++] = *connector;
        }
  
+       save_set.crtc = set->crtc;
+       save_set.mode = &set->crtc->mode;
+       save_set.x = set->crtc->x;
+       save_set.y = set->crtc->y;
+       save_set.fb = set->crtc->fb;
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
        if (set->crtc->fb != set->fb) {
@@@ -722,6 -751,12 +752,12 @@@ fail
                *connector = save_connectors[count++];
        }
  
+       /* Try to restore the config */
+       if (mode_changed &&
+           !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+                                     save_set.y, save_set.fb))
+               DRM_ERROR("failed to restore config after modeset failure\n");
        kfree(save_connectors);
        kfree(save_encoders);
        kfree(save_crtcs);
@@@ -812,19 -847,13 +848,19 @@@ void drm_helper_connector_dpms(struct d
  EXPORT_SYMBOL(drm_helper_connector_dpms);
  
  int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
 -                                 struct drm_mode_fb_cmd *mode_cmd)
 +                                 struct drm_mode_fb_cmd2 *mode_cmd)
  {
 +      int i;
 +
        fb->width = mode_cmd->width;
        fb->height = mode_cmd->height;
 -      fb->pitch = mode_cmd->pitch;
 -      fb->bits_per_pixel = mode_cmd->bpp;
 -      fb->depth = mode_cmd->depth;
 +      for (i = 0; i < 4; i++) {
 +              fb->pitches[i] = mode_cmd->pitches[i];
 +              fb->offsets[i] = mode_cmd->offsets[i];
 +      }
 +      drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
 +                                  &fb->bits_per_pixel);
 +      fb->pixel_format = mode_cmd->pixel_format;
  
        return 0;
  }
index eaf25ffd9a46c403cbe7f2e96a32046a6de20c27,40c187c60f44fcb2ea45bedede0fe003f9e8ebb2..bc5febe45762a4318aa98976b08f969c766ba21c
@@@ -125,7 -125,7 +125,7 @@@ static struct drm_ioctl_desc drm_ioctls
        DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
  
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
  
        DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
  
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
  
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 +      DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 +      DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 +      DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 +      DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
index 73893e5068a4f7198e60eab0cb6d1777e73b375a,ee43cc22085304f7f07f267cd63a7d2be05d249a..7777d41d1cda7e12e624abaada77d40741ac1195
  #include "drmP.h"
  #include "drm_crtc_helper.h"
  
+ #include "exynos_drm_crtc.h"
  #include "exynos_drm_drv.h"
  #include "exynos_drm_fb.h"
  #include "exynos_drm_encoder.h"
+ #include "exynos_drm_gem.h"
  #include "exynos_drm_buf.h"
  
  #define to_exynos_crtc(x)     container_of(x, struct exynos_drm_crtc,\
                                drm_crtc)
  
- /*
-  * Exynos specific crtc postion structure.
-  *
-  * @fb_x: offset x on a framebuffer to be displyed
-  *    - the unit is screen coordinates.
-  * @fb_y: offset y on a framebuffer to be displayed
-  *    - the unit is screen coordinates.
-  * @crtc_x: offset x on hardware screen.
-  * @crtc_y: offset y on hardware screen.
-  * @crtc_w: width of hardware screen.
-  * @crtc_h: height of hardware screen.
-  */
- struct exynos_drm_crtc_pos {
-       unsigned int fb_x;
-       unsigned int fb_y;
-       unsigned int crtc_x;
-       unsigned int crtc_y;
-       unsigned int crtc_w;
-       unsigned int crtc_h;
- };
  /*
   * Exynos specific crtc structure.
   *
@@@ -85,30 -66,31 +66,31 @@@ static void exynos_drm_crtc_apply(struc
  
        exynos_drm_fn_encoder(crtc, overlay,
                        exynos_drm_encoder_crtc_mode_set);
-       exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit);
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
  }
  
static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
-                                      struct drm_framebuffer *fb,
-                                      struct drm_display_mode *mode,
-                                      struct exynos_drm_crtc_pos *pos)
+ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+                             struct drm_framebuffer *fb,
+                             struct drm_display_mode *mode,
+                             struct exynos_drm_crtc_pos *pos)
  {
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
        unsigned int actual_w;
        unsigned int actual_h;
  
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
  
-       overlay->paddr = entry->paddr;
-       overlay->vaddr = entry->vaddr;
+       overlay->dma_addr = buffer->dma_addr;
+       overlay->vaddr = buffer->kvaddr;
  
-       DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
+       DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
                        (unsigned long)overlay->vaddr,
-                       (unsigned long)overlay->paddr);
+                       (unsigned long)overlay->dma_addr);
  
        actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
        actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
        overlay->fb_width = fb->width;
        overlay->fb_height = fb->height;
        overlay->bpp = fb->bits_per_pixel;
 -      overlay->pitch = fb->pitch;
 +      overlay->pitch = fb->pitches[0];
  
        /* set overlay range to be displayed. */
        overlay->crtc_x = pos->crtc_x;
@@@ -171,9 -153,26 +153,26 @@@ static int exynos_drm_crtc_update(struc
  
  static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
  {
-       DRM_DEBUG_KMS("%s\n", __FILE__);
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  
-       /* TODO */
+       DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                               exynos_drm_encoder_crtc_commit);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+               exynos_drm_fn_encoder(crtc, NULL,
+                               exynos_drm_encoder_crtc_disable);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
+       }
  }
  
  static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
  
  static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
  {
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
        DRM_DEBUG_KMS("%s\n", __FILE__);
  
-       /* drm framework doesn't check NULL. */
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
  }
  
  static bool
index 81fba29b696d037485226f4b25e53c3050fcc30f,836f4100818710e830229b985591bfc85a047f03..f79f768a56cae63ee63b72600a9f1c2aed2cd342
@@@ -33,6 -33,7 +33,7 @@@
  
  #include "exynos_drm_drv.h"
  #include "exynos_drm_fb.h"
+ #include "exynos_drm_gem.h"
  #include "exynos_drm_buf.h"
  
  #define MAX_CONNECTOR         4
@@@ -85,36 -86,34 +86,34 @@@ static struct fb_ops exynos_drm_fb_ops 
  };
  
  static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
-                                    struct drm_framebuffer *fb,
-                                    unsigned int fb_width,
-                                    unsigned int fb_height)
+                                    struct drm_framebuffer *fb)
  {
        struct fb_info *fbi = helper->fbdev;
        struct drm_device *dev = helper->dev;
        struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
-       struct exynos_drm_buf_entry *entry;
-       unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
+       struct exynos_drm_gem_buf *buffer;
+       unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
        unsigned long offset;
  
        DRM_DEBUG_KMS("%s\n", __FILE__);
  
        exynos_fb->fb = fb;
  
 -      drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
 +      drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
-       drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
+       drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
  
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
  
        offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
 -      offset += fbi->var.yoffset * fb->pitch;
 +      offset += fbi->var.yoffset * fb->pitches[0];
  
-       dev->mode_config.fb_base = entry->paddr;
-       fbi->screen_base = entry->vaddr + offset;
-       fbi->fix.smem_start = entry->paddr + offset;
+       dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+       fbi->screen_base = buffer->kvaddr + offset;
+       fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
  
@@@ -171,8 -170,7 +170,7 @@@ static int exynos_drm_fbdev_create(stru
                goto out;
        }
  
-       ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       ret = exynos_drm_fbdev_update(helper, helper->fb);
        if (ret < 0)
                fb_dealloc_cmap(&fbi->cmap);
  
@@@ -235,8 -233,7 +233,7 @@@ static int exynos_drm_fbdev_recreate(st
        }
  
        helper->fb = exynos_fbdev->fb;
-       return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       return exynos_drm_fbdev_update(helper, helper->fb);
  }
  
  static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
@@@ -405,6 -402,18 +402,18 @@@ int exynos_drm_fbdev_reinit(struct drm_
        fb_helper = private->fb_helper;
  
        if (fb_helper) {
+               struct list_head temp_list;
+               INIT_LIST_HEAD(&temp_list);
+               /*
+                * fb_helper is reintialized but kernel fb is reused
+                * so kernel_fb_list need to be backuped and restored
+                */
+               if (!list_empty(&fb_helper->kernel_fb_list))
+                       list_replace_init(&fb_helper->kernel_fb_list,
+                                       &temp_list);
                drm_fb_helper_fini(fb_helper);
  
                ret = drm_fb_helper_init(dev, fb_helper,
                        return ret;
                }
  
+               if (!list_empty(&temp_list))
+                       list_replace(&temp_list, &fb_helper->kernel_fb_list);
                ret = drm_fb_helper_single_add_all_connectors(fb_helper);
                if (ret < 0) {
                        DRM_ERROR("failed to add fb helper to connectors\n");
index 9f592703c3696842d8a858de06bec880cd832a65,a1103fc6597dde91958658d4d6faaabaec38e803..22c8ab70db2c041c9d10061a5b9304b27f78be3c
@@@ -58,17 -58,17 +58,17 @@@ module_param_named(powersave, i915_powe
  MODULE_PARM_DESC(powersave,
                "Enable powersavings, fbc, downclocking, etc. (default: true)");
  
unsigned int i915_semaphores __read_mostly = 0;
int i915_semaphores __read_mostly = -1;
  module_param_named(semaphores, i915_semaphores, int, 0600);
  MODULE_PARM_DESC(semaphores,
-               "Use semaphores for inter-ring sync (default: false)");
+               "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
  
unsigned int i915_enable_rc6 __read_mostly = 0;
int i915_enable_rc6 __read_mostly = -1;
  module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
  MODULE_PARM_DESC(i915_enable_rc6,
-               "Enable power-saving render C-state 6 (default: true)");
+               "Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
  
unsigned int i915_enable_fbc __read_mostly = -1;
+ int i915_enable_fbc __read_mostly = -1;
  module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
  MODULE_PARM_DESC(i915_enable_fbc,
                "Enable frame buffer compression for power savings "
@@@ -80,7 -80,7 +80,7 @@@ MODULE_PARM_DESC(lvds_downclock
                "Use panel (LVDS/eDP) downclocking for power savings "
                "(default: false)");
  
unsigned int i915_panel_use_ssc __read_mostly = -1;
+ int i915_panel_use_ssc __read_mostly = -1;
  module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
  MODULE_PARM_DESC(lvds_use_ssc,
                "Use Spread Spectrum Clock with panels [LVDS/eDP] "
@@@ -107,7 -107,7 +107,7 @@@ static struct drm_driver driver
  extern int intel_agp_enabled;
  
  #define INTEL_VGA_DEVICE(id, info) {          \
-       .class = PCI_CLASS_DISPLAY_VGA << 8,    \
+       .class = PCI_BASE_CLASS_DISPLAY << 16,  \
        .class_mask = 0xff0000,                 \
        .vendor = 0x8086,                       \
        .device = id,                           \
@@@ -328,7 -328,7 +328,7 @@@ void intel_detect_pch(struct drm_devic
        }
  }
  
static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+ void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
  {
        int count;
  
                udelay(10);
  }
  
+ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+ {
+       int count;
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
+               udelay(10);
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
+       POSTING_READ(FORCEWAKE_MT);
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0)
+               udelay(10);
+ }
  /*
   * Generally this is called implicitly by the register read function. However,
   * if some sequence requires the GT to not power down then this function should
@@@ -356,15 -372,21 +372,21 @@@ void gen6_gt_force_wake_get(struct drm_
  
        /* Forcewake is atomic in case we get in here without the lock */
        if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
-               __gen6_gt_force_wake_get(dev_priv);
+               dev_priv->display.force_wake_get(dev_priv);
  }
  
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+ void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
  {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
        POSTING_READ(FORCEWAKE);
  }
  
+ void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+ {
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
+       POSTING_READ(FORCEWAKE_MT);
+ }
  /*
   * see gen6_gt_force_wake_get()
   */
@@@ -373,7 -395,7 +395,7 @@@ void gen6_gt_force_wake_put(struct drm_
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
  
        if (atomic_dec_and_test(&dev_priv->forcewake_count))
-               __gen6_gt_force_wake_put(dev_priv);
+               dev_priv->display.force_wake_put(dev_priv);
  }
  
  void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@@@ -788,24 -810,9 +810,24 @@@ static struct vm_operations_struct i915
        .close = drm_gem_vm_close,
  };
  
 +static const struct file_operations i915_driver_fops = {
 +      .owner = THIS_MODULE,
 +      .open = drm_open,
 +      .release = drm_release,
 +      .unlocked_ioctl = drm_ioctl,
 +      .mmap = drm_gem_mmap,
 +      .poll = drm_poll,
 +      .fasync = drm_fasync,
 +      .read = drm_read,
 +#ifdef CONFIG_COMPAT
 +      .compat_ioctl = i915_compat_ioctl,
 +#endif
 +      .llseek = noop_llseek,
 +};
 +
  static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
        .dumb_map_offset = i915_gem_mmap_gtt,
        .dumb_destroy = i915_gem_dumb_destroy,
        .ioctls = i915_ioctls,
 -      .fops = {
 -               .owner = THIS_MODULE,
 -               .open = drm_open,
 -               .release = drm_release,
 -               .unlocked_ioctl = drm_ioctl,
 -               .mmap = drm_gem_mmap,
 -               .poll = drm_poll,
 -               .fasync = drm_fasync,
 -               .read = drm_read,
 -#ifdef CONFIG_COMPAT
 -               .compat_ioctl = i915_compat_ioctl,
 -#endif
 -               .llseek = noop_llseek,
 -      },
 -
 +      .fops = &i915_driver_fops,
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = DRIVER_DATE,
@@@ -904,8 -925,9 +926,9 @@@ MODULE_LICENSE("GPL and additional righ
  /* We give fast paths for the really cool registers */
  #define NEEDS_FORCE_WAKE(dev_priv, reg) \
        (((dev_priv)->info->gen >= 6) && \
-       ((reg) < 0x40000) && \
-       ((reg) != FORCEWAKE))
+        ((reg) < 0x40000) &&            \
+        ((reg) != FORCEWAKE) &&         \
+        ((reg) != ECOBUS))
  
  #define __i915_read(x, y) \
  u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
index 96643ee240dafbf4604635efbf66bbaaaac078b2,b40004b559771dc0244814335d44fb1537625087..3700df47ad931100ea94b4953309182335026e1a
@@@ -824,6 -824,7 +824,7 @@@ static void i915_gem_record_fences(stru
  
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@@ -1204,7 -1205,7 +1205,7 @@@ static void i915_pageflip_stall_check(s
        } else {
                int dspaddr = DSPADDR(intel_crtc->plane);
                stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
 -                                                      crtc->y * crtc->fb->pitch +
 +                                                      crtc->y * crtc->fb->pitches[0] +
                                                        crtc->x * crtc->fb->bits_per_pixel/8);
        }
  
index 517bf0cda3e5abf2aefeea7edaa5a166f2f4cd0a,a26d5b0a36908c3d7ddd5c9c7407921fd2826db9..853f2f0acaa22149b33fd0bf26274fda7345c757
   */
  #define   PP_READY            (1 << 30)
  #define   PP_SEQUENCE_NONE    (0 << 28)
- #define   PP_SEQUENCE_ON      (1 << 28)
- #define   PP_SEQUENCE_OFF     (2 << 28)
- #define   PP_SEQUENCE_MASK    0x30000000
+ #define   PP_SEQUENCE_POWER_UP        (1 << 28)
+ #define   PP_SEQUENCE_POWER_DOWN (2 << 28)
+ #define   PP_SEQUENCE_MASK    (3 << 28)
+ #define   PP_SEQUENCE_SHIFT   28
  #define   PP_CYCLE_DELAY_ACTIVE       (1 << 27)
- #define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
  #define   PP_SEQUENCE_STATE_MASK 0x0000000f
+ #define   PP_SEQUENCE_STATE_OFF_IDLE  (0x0 << 0)
+ #define   PP_SEQUENCE_STATE_OFF_S0_1  (0x1 << 0)
+ #define   PP_SEQUENCE_STATE_OFF_S0_2  (0x2 << 0)
+ #define   PP_SEQUENCE_STATE_OFF_S0_3  (0x3 << 0)
+ #define   PP_SEQUENCE_STATE_ON_IDLE   (0x8 << 0)
+ #define   PP_SEQUENCE_STATE_ON_S1_0   (0x9 << 0)
+ #define   PP_SEQUENCE_STATE_ON_S1_2   (0xa << 0)
+ #define   PP_SEQUENCE_STATE_ON_S1_3   (0xb << 0)
+ #define   PP_SEQUENCE_STATE_RESET     (0xf << 0)
  #define PP_CONTROL    0x61204
  #define   POWER_TARGET_ON     (1 << 0)
  #define PP_ON_DELAYS  0x61208
  #define   PIPECONF_PROGRESSIVE        (0 << 21)
  #define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
  #define   PIPECONF_INTERLACE_FIELD_0_ONLY             (7 << 21)
 +#define   PIPECONF_INTERLACE_MASK     (7 << 21)
  #define   PIPECONF_CXSR_DOWNCLOCK     (1<<16)
  #define   PIPECONF_BPP_MASK   (0x000000e0)
  #define   PIPECONF_BPP_8      (0<<5)
  /* or SDVOB */
  #define HDMIB   0xe1140
  #define  PORT_ENABLE    (1 << 31)
- #define  TRANSCODER_A   (0)
- #define  TRANSCODER_B   (1 << 30)
- #define  TRANSCODER(pipe)     ((pipe) << 30)
- #define  TRANSCODER_MASK   (1 << 30)
+ #define  TRANSCODER(pipe)       ((pipe) << 30)
+ #define  TRANSCODER_CPT(pipe)   ((pipe) << 29)
+ #define  TRANSCODER_MASK        (1 << 30)
+ #define  TRANSCODER_MASK_CPT    (3 << 29)
  #define  COLOR_FORMAT_8bpc      (0)
  #define  COLOR_FORMAT_12bpc     (3 << 26)
  #define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
  #define  EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B  (0x38<<22)
  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_SNB      (0x3f<<22)
  
+ /* IVB */
+ #define EDP_LINK_TRAIN_400MV_0DB_IVB          (0x24 <<22)
+ #define EDP_LINK_TRAIN_400MV_3_5DB_IVB                (0x2a <<22)
+ #define EDP_LINK_TRAIN_400MV_6DB_IVB          (0x2f <<22)
+ #define EDP_LINK_TRAIN_600MV_0DB_IVB          (0x30 <<22)
+ #define EDP_LINK_TRAIN_600MV_3_5DB_IVB                (0x36 <<22)
+ #define EDP_LINK_TRAIN_800MV_0DB_IVB          (0x38 <<22)
+ #define EDP_LINK_TRAIN_800MV_3_5DB_IVB                (0x33 <<22)
+ /* legacy values */
+ #define EDP_LINK_TRAIN_500MV_0DB_IVB          (0x00 <<22)
+ #define EDP_LINK_TRAIN_1000MV_0DB_IVB         (0x20 <<22)
+ #define EDP_LINK_TRAIN_500MV_3_5DB_IVB                (0x02 <<22)
+ #define EDP_LINK_TRAIN_1000MV_3_5DB_IVB               (0x22 <<22)
+ #define EDP_LINK_TRAIN_1000MV_6DB_IVB         (0x23 <<22)
+ #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB      (0x3f<<22)
  #define  FORCEWAKE                            0xA18C
  #define  FORCEWAKE_ACK                                0x130090
+ #define  FORCEWAKE_MT                         0xa188 /* multi-threaded */
+ #define  FORCEWAKE_MT_ACK                     0x130040
+ #define  ECOBUS                                       0xa180
+ #define    FORCEWAKE_MT_ENABLE                        (1<<5)
  
  #define  GT_FIFO_FREE_ENTRIES                 0x120008
  #define    GT_FIFO_NUM_RESERVED_ENTRIES               20
  
+ #define GEN6_UCGCTL2                          0x9404
+ # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE             (1 << 12)
+ # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE              (1 << 11)
  #define GEN6_RPNSWREQ                         0xA008
  #define   GEN6_TURBO_DISABLE                  (1<<31)
  #define   GEN6_FREQUENCY(x)                   ((x)<<25)
index 8ecbc2f116332b815c6c8219467dacccc8983631,d809b038ca88a8e29276773c06d3da8663395e3d..5a3e7853003f1bbd31809535bc855ecce40a47b5
@@@ -38,8 -38,8 +38,8 @@@
  #include "i915_drv.h"
  #include "i915_trace.h"
  #include "drm_dp_helper.h"
  #include "drm_crtc_helper.h"
+ #include <linux/dma_remapping.h>
  
  #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
  
@@@ -1511,8 -1511,8 +1511,8 @@@ static void i8xx_enable_fbc(struct drm_
        u32 fbc_ctl, fbc_ctl2;
  
        cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
 -      if (fb->pitch < cfb_pitch)
 -              cfb_pitch = fb->pitch;
 +      if (fb->pitches[0] < cfb_pitch)
 +              cfb_pitch = fb->pitches[0];
  
        /* FBC_CTL wants 64B units */
        cfb_pitch = (cfb_pitch / 64) - 1;
@@@ -2073,11 -2073,11 +2073,11 @@@ static int i9xx_update_plane(struct drm
        I915_WRITE(reg, dspcntr);
  
        Start = obj->gtt_offset;
 -      Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
 +      Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
  
        DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
 -                    Start, Offset, x, y, fb->pitch);
 -      I915_WRITE(DSPSTRIDE(plane), fb->pitch);
 +                    Start, Offset, x, y, fb->pitches[0]);
 +      I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        if (INTEL_INFO(dev)->gen >= 4) {
                I915_WRITE(DSPSURF(plane), Start);
                I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
@@@ -2154,11 -2154,11 +2154,11 @@@ static int ironlake_update_plane(struc
        I915_WRITE(reg, dspcntr);
  
        Start = obj->gtt_offset;
 -      Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
 +      Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
  
        DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
 -                    Start, Offset, x, y, fb->pitch);
 -      I915_WRITE(DSPSTRIDE(plane), fb->pitch);
 +                    Start, Offset, x, y, fb->pitches[0]);
 +      I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        I915_WRITE(DSPSURF(plane), Start);
        I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
        I915_WRITE(DSPADDR(plane), Offset);
@@@ -2933,7 -2933,8 +2933,8 @@@ static void ironlake_pch_enable(struct 
  
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) &&
-           intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+           (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+            intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
                u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
@@@ -4669,6 -4670,7 +4670,7 @@@ static inline bool intel_panel_use_ssc(
  /**
   * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
   * @crtc: CRTC structure
+  * @mode: requested mode
   *
   * A pipe may be connected to one or more outputs.  Based on the depth of the
   * attached framebuffer, choose a good color depth to use on the pipe.
   *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
   *    Displays may support a restricted set as well, check EDID and clamp as
   *      appropriate.
+  *    DP may want to dither down to 6bpc to fit larger modes
   *
   * RETURNS:
   * Dithering requirement (i.e. false if display bpc and pipe bpc match,
   * true if they don't match).
   */
  static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
-                                        unsigned int *pipe_bpp)
+                                        unsigned int *pipe_bpp,
+                                        struct drm_display_mode *mode)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
                                lvds_bpc = 6;
  
                        if (lvds_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
                                display_bpc = lvds_bpc;
                        }
                        continue;
                        unsigned int edp_bpc = dev_priv->edp.bpp / 3;
  
                        if (edp_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
                                display_bpc = edp_bpc;
                        }
                        continue;
                        /* Don't use an invalid EDID bpc value */
                        if (connector->display_info.bpc &&
                            connector->display_info.bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
                                display_bpc = connector->display_info.bpc;
                        }
                }
                 */
                if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
                        if (display_bpc > 8 && display_bpc < 12) {
-                               DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
                                display_bpc = 12;
                        } else {
-                               DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
                                display_bpc = 8;
                        }
                }
        }
  
+       if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+               DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
+               display_bpc = 6;
+       }
        /*
         * We could just drive the pipe at the highest bpc all the time and
         * enable dithering as needed, but that costs bandwidth.  So choose
  
        display_bpc = min(display_bpc, bpc);
  
-       DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
-                        bpc, display_bpc);
+       DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+                     bpc, display_bpc);
  
        *pipe_bpp = display_bpc * 3;
  
@@@ -5018,6 -5027,16 +5027,16 @@@ static int i9xx_crtc_mode_set(struct dr
                        pipeconf &= ~PIPECONF_DOUBLE_WIDE;
        }
  
+       /* default to 8bpc */
+       pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
+       if (is_dp) {
+               if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+                       pipeconf |= PIPECONF_BPP_6 |
+                                   PIPECONF_DITHER_EN |
+                                   PIPECONF_DITHER_TYPE_SP;
+               }
+       }
        dpll |= DPLL_VCO_ENABLE;
  
        DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
                adjusted_mode->crtc_vsync_end -= 1;
                adjusted_mode->crtc_vsync_start -= 1;
        } else
 -              pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
 +              pipeconf &= ~PIPECONF_INTERLACE_MASK; /* progressive */
  
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@@ -5479,7 -5498,7 +5498,7 @@@ static int ironlake_crtc_mode_set(struc
        /* determine panel color depth */
        temp = I915_READ(PIPECONF(pipe));
        temp &= ~PIPE_BPC_MASK;
-       dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+       dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
        switch (pipe_bpp) {
        case 18:
                temp |= PIPE_6BPC;
        pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
        if ((is_lvds && dev_priv->lvds_dither) || dither) {
                pipeconf |= PIPECONF_DITHER_EN;
-               pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+               pipeconf |= PIPECONF_DITHER_TYPE_SP;
        }
        if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@@ -6279,7 -6298,7 +6298,7 @@@ static struct drm_display_mode load_det
  
  static struct drm_framebuffer *
  intel_framebuffer_create(struct drm_device *dev,
 -                       struct drm_mode_fb_cmd *mode_cmd,
 +                       struct drm_mode_fb_cmd2 *mode_cmd,
                         struct drm_i915_gem_object *obj)
  {
        struct intel_framebuffer *intel_fb;
@@@ -6321,7 -6340,7 +6340,7 @@@ intel_framebuffer_create_for_mode(struc
                                  int depth, int bpp)
  {
        struct drm_i915_gem_object *obj;
 -      struct drm_mode_fb_cmd mode_cmd;
 +      struct drm_mode_fb_cmd2 mode_cmd;
  
        obj = i915_gem_alloc_object(dev,
                                    intel_framebuffer_size_for_mode(mode, bpp));
  
        mode_cmd.width = mode->hdisplay;
        mode_cmd.height = mode->vdisplay;
 -      mode_cmd.depth = depth;
 -      mode_cmd.bpp = bpp;
 -      mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp);
 +      mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
 +                                                              bpp);
 +      mode_cmd.pixel_format = 0;
  
        return intel_framebuffer_create(dev, &mode_cmd, obj);
  }
@@@ -6353,11 -6372,11 +6372,11 @@@ mode_fits_in_fbdev(struct drm_device *d
                return NULL;
  
        fb = &dev_priv->fbdev->ifb.base;
 -      if (fb->pitch < intel_framebuffer_pitch_for_width(mode->hdisplay,
 -                                                        fb->bits_per_pixel))
 +      if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
 +                                                             fb->bits_per_pixel))
                return NULL;
  
 -      if (obj->base.size < mode->vdisplay * fb->pitch)
 +      if (obj->base.size < mode->vdisplay * fb->pitches[0])
                return NULL;
  
        return fb;
@@@ -6990,7 -7009,7 +7009,7 @@@ static int intel_gen2_queue_flip(struc
                goto out;
  
        /* Offset into the new buffer for cases of shared fbs between CRTCs */
 -      offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
 +      offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
  
        ret = BEGIN_LP_RING(6);
        if (ret)
        OUT_RING(MI_NOOP);
        OUT_RING(MI_DISPLAY_FLIP |
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 -      OUT_RING(fb->pitch);
 +      OUT_RING(fb->pitches[0]);
        OUT_RING(obj->gtt_offset + offset);
        OUT_RING(MI_NOOP);
        ADVANCE_LP_RING();
@@@ -7031,7 -7050,7 +7050,7 @@@ static int intel_gen3_queue_flip(struc
                goto out;
  
        /* Offset into the new buffer for cases of shared fbs between CRTCs */
 -      offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
 +      offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
  
        ret = BEGIN_LP_RING(6);
        if (ret)
        OUT_RING(MI_NOOP);
        OUT_RING(MI_DISPLAY_FLIP_I915 |
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 -      OUT_RING(fb->pitch);
 +      OUT_RING(fb->pitches[0]);
        OUT_RING(obj->gtt_offset + offset);
        OUT_RING(MI_NOOP);
  
@@@ -7078,7 -7097,7 +7097,7 @@@ static int intel_gen4_queue_flip(struc
         */
        OUT_RING(MI_DISPLAY_FLIP |
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 -      OUT_RING(fb->pitch);
 +      OUT_RING(fb->pitches[0]);
        OUT_RING(obj->gtt_offset | obj->tiling_mode);
  
        /* XXX Enabling the panel-fitter across page-flip is so far
@@@ -7113,7 -7132,7 +7132,7 @@@ static int intel_gen6_queue_flip(struc
  
        OUT_RING(MI_DISPLAY_FLIP |
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 -      OUT_RING(fb->pitch | obj->tiling_mode);
 +      OUT_RING(fb->pitches[0] | obj->tiling_mode);
        OUT_RING(obj->gtt_offset);
  
        pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
@@@ -7149,7 -7168,7 +7168,7 @@@ static int intel_gen7_queue_flip(struc
                goto out;
  
        intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
 -      intel_ring_emit(ring, (fb->pitch | obj->tiling_mode));
 +      intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
        intel_ring_emit(ring, (obj->gtt_offset));
        intel_ring_emit(ring, (MI_NOOP));
        intel_ring_advance(ring);
@@@ -7188,11 -7207,16 +7207,16 @@@ static int intel_crtc_page_flip(struct 
        work->old_fb_obj = intel_fb->obj;
        INIT_WORK(&work->work, intel_unpin_work_fn);
  
+       ret = drm_vblank_get(dev, intel_crtc->pipe);
+       if (ret)
+               goto free_work;
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
                spin_unlock_irqrestore(&dev->event_lock, flags);
                kfree(work);
+               drm_vblank_put(dev, intel_crtc->pipe);
  
                DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                return -EBUSY;
  
        crtc->fb = fb;
  
-       ret = drm_vblank_get(dev, intel_crtc->pipe);
-       if (ret)
-               goto cleanup_objs;
        work->pending_flip_obj = obj;
  
        work->enable_stall_check = true;
  
  cleanup_pending:
        atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
- cleanup_objs:
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
        intel_crtc->unpin_work = NULL;
        spin_unlock_irqrestore(&dev->event_lock, flags);
  
+       drm_vblank_put(dev, intel_crtc->pipe);
+ free_work:
        kfree(work);
  
        return ret;
@@@ -7573,7 -7594,7 +7594,7 @@@ static const struct drm_framebuffer_fun
  
  int intel_framebuffer_init(struct drm_device *dev,
                           struct intel_framebuffer *intel_fb,
 -                         struct drm_mode_fb_cmd *mode_cmd,
 +                         struct drm_mode_fb_cmd2 *mode_cmd,
                           struct drm_i915_gem_object *obj)
  {
        int ret;
        if (obj->tiling_mode == I915_TILING_Y)
                return -EINVAL;
  
 -      if (mode_cmd->pitch & 63)
 +      if (mode_cmd->pitches[0] & 63)
                return -EINVAL;
  
 -      switch (mode_cmd->bpp) {
 -      case 8:
 -      case 16:
 -              /* Only pre-ILK can handle 5:5:5 */
 -              if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
 -                      return -EINVAL;
 +      switch (mode_cmd->pixel_format) {
 +      case DRM_FORMAT_RGB332:
 +      case DRM_FORMAT_RGB565:
 +      case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_ARGB8888:
 +      case DRM_FORMAT_XRGB2101010:
 +      case DRM_FORMAT_ARGB2101010:
 +              /* RGB formats are common across chipsets */
                break;
 -
 -      case 24:
 -      case 32:
 +      case DRM_FORMAT_YUYV:
 +      case DRM_FORMAT_UYVY:
 +      case DRM_FORMAT_YVYU:
 +      case DRM_FORMAT_VYUY:
                break;
        default:
 +              DRM_ERROR("unsupported pixel format\n");
                return -EINVAL;
        }
  
  static struct drm_framebuffer *
  intel_user_framebuffer_create(struct drm_device *dev,
                              struct drm_file *filp,
 -                            struct drm_mode_fb_cmd *mode_cmd)
 +                            struct drm_mode_fb_cmd2 *mode_cmd)
  {
        struct drm_i915_gem_object *obj;
  
 -      obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
 +      obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
 +                                              mode_cmd->handles[0]));
        if (&obj->base == NULL)
                return ERR_PTR(-ENOENT);
  
@@@ -7891,6 -7907,33 +7912,33 @@@ void intel_init_emon(struct drm_device 
        dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
  }
  
+ static bool intel_enable_rc6(struct drm_device *dev)
+ {
+       /*
+        * Respect the kernel parameter if it is set
+        */
+       if (i915_enable_rc6 >= 0)
+               return i915_enable_rc6;
+       /*
+        * Disable RC6 on Ironlake
+        */
+       if (INTEL_INFO(dev)->gen == 5)
+               return 0;
+       /*
+        * Enable rc6 on Sandybridge if DMA remapping is disabled
+        */
+       if (INTEL_INFO(dev)->gen == 6) {
+               DRM_DEBUG_DRIVER("Sandybridge: intel_iommu_enabled %s -- RC6 %sabled\n",
+                                intel_iommu_enabled ? "true" : "false",
+                                !intel_iommu_enabled ? "en" : "dis");
+               return !intel_iommu_enabled;
+       }
+       DRM_DEBUG_DRIVER("RC6 enabled\n");
+       return 1;
+ }
  void gen6_enable_rps(struct drm_i915_private *dev_priv)
  {
        u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
        I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
  
-       if (i915_enable_rc6)
+       if (intel_enable_rc6(dev_priv->dev))
                rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
                        GEN6_RC_CTL_RC6_ENABLE;
  
@@@ -8153,6 -8196,20 +8201,20 @@@ static void gen6_init_clock_gating(stru
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
  
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
@@@ -8362,7 -8419,7 +8424,7 @@@ void ironlake_enable_rc6(struct drm_dev
        /* rc6 disabled by default due to repeated reports of hanging during
         * boot and resume.
         */
-       if (!i915_enable_rc6)
+       if (!intel_enable_rc6(dev))
                return;
  
        mutex_lock(&dev->struct_mutex);
@@@ -8481,6 -8538,28 +8543,28 @@@ static void intel_init_display(struct d
  
        /* For FIFO watermark updates */
        if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
+               dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
+               /* IVB configs may use multi-threaded forcewake */
+               if (IS_IVYBRIDGE(dev)) {
+                       u32     ecobus;
+                       mutex_lock(&dev->struct_mutex);
+                       __gen6_gt_force_wake_mt_get(dev_priv);
+                       ecobus = I915_READ(ECOBUS);
+                       __gen6_gt_force_wake_mt_put(dev_priv);
+                       mutex_unlock(&dev->struct_mutex);
+                       if (ecobus & FORCEWAKE_MT_ENABLE) {
+                               DRM_DEBUG_KMS("Using MT version of forcewake\n");
+                               dev_priv->display.force_wake_get =
+                                       __gen6_gt_force_wake_mt_get;
+                               dev_priv->display.force_wake_put =
+                                       __gen6_gt_force_wake_mt_put;
+                       }
+               }
                if (HAS_PCH_IBX(dev))
                        dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
                else if (HAS_PCH_CPT(dev))
index 23c56221fe8ff7fb95d2d7f6438c6c19d43565b8,a1b4343814e8faac807384057ba51a541746b6bd..82a459bfccbc79c2a6b327da039fee68efa83195
  /* drm_display_mode->private_flags */
  #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
  #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
+ #define INTEL_MODE_DP_FORCE_6BPC (0x10)
  
  static inline void
  intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@@@ -359,7 -360,7 +360,7 @@@ extern int intel_pin_and_fence_fb_obj(s
  
  extern int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *ifb,
 -                                struct drm_mode_fb_cmd *mode_cmd,
 +                                struct drm_mode_fb_cmd2 *mode_cmd,
                                  struct drm_i915_gem_object *obj);
  extern int intel_fbdev_init(struct drm_device *dev);
  extern void intel_fbdev_fini(struct drm_device *dev);
index b1b33a108b318902aa65cd9deb2f20aba220641b,7cc37e69086012594a1dff3a2e255f66e396e656..f12dd0f39211869184cc7b4ad21fdd6132aa3ad8
@@@ -28,7 -28,6 +28,7 @@@
   */
  
  #include "drmP.h"
 +#include "ttm/ttm_page_alloc.h"
  
  #include "nouveau_drm.h"
  #include "nouveau_drv.h"
@@@ -93,7 -92,6 +93,7 @@@ nouveau_bo_new(struct drm_device *dev, 
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_bo *nvbo;
 +      size_t acc_size;
        int ret;
  
        nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
        nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
        nouveau_bo_placement_set(nvbo, flags, 0);
  
 +      acc_size = ttm_bo_dma_acc_size(&dev_priv->ttm.bdev, size,
 +                                     sizeof(struct nouveau_bo));
 +
        ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
                          ttm_bo_type_device, &nvbo->placement,
 -                        align >> PAGE_SHIFT, 0, false, NULL, size,
 +                        align >> PAGE_SHIFT, 0, false, NULL, acc_size,
                          nouveau_bo_del_ttm);
        if (ret) {
                /* ttm will call nouveau_bo_del_ttm if it fails.. */
@@@ -153,7 -148,7 +153,7 @@@ set_placement_range(struct nouveau_bo *
  
        if (dev_priv->card_type == NV_10 &&
            nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
-           nvbo->bo.mem.num_pages < vram_pages / 2) {
+           nvbo->bo.mem.num_pages < vram_pages / 4) {
                /*
                 * Make sure that the color and depth buffers are handled
                 * by independent memory controller units. Up to a 9x
@@@ -348,10 -343,8 +348,10 @@@ nouveau_bo_wr32(struct nouveau_bo *nvbo
                *mem = val;
  }
  
 -static struct ttm_backend *
 -nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
 +static struct ttm_tt *
 +nouveau_ttm_tt_create(struct ttm_bo_device *bdev,
 +                    unsigned long size, uint32_t page_flags,
 +                    struct page *dummy_read_page)
  {
        struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
        struct drm_device *dev = dev_priv->dev;
        switch (dev_priv->gart_info.type) {
  #if __OS_HAS_AGP
        case NOUVEAU_GART_AGP:
 -              return ttm_agp_backend_init(bdev, dev->agp->bridge);
 +              return ttm_agp_tt_create(bdev, dev->agp->bridge,
 +                                       size, page_flags, dummy_read_page);
  #endif
        case NOUVEAU_GART_PDMA:
        case NOUVEAU_GART_HW:
 -              return nouveau_sgdma_init_ttm(dev);
 +              return nouveau_sgdma_create_ttm(bdev, size, page_flags,
 +                                              dummy_read_page);
        default:
                NV_ERROR(dev, "Unknown GART type %d\n",
                         dev_priv->gart_info.type);
@@@ -815,10 -806,10 +815,10 @@@ nouveau_bo_move_ntfy(struct ttm_buffer_
        struct nouveau_vma *vma;
  
        list_for_each_entry(vma, &nvbo->vma_list, head) {
 -              if (new_mem->mem_type == TTM_PL_VRAM) {
 +              if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
                        nouveau_vm_map(vma, new_mem->mm_node);
                } else
 -              if (new_mem->mem_type == TTM_PL_TT &&
 +              if (new_mem && new_mem->mem_type == TTM_PL_TT &&
                    nvbo->page_shift == vma->vm->spg_shift) {
                        nouveau_vm_map_sg(vma, 0, new_mem->
                                          num_pages << PAGE_SHIFT,
@@@ -1053,81 -1044,8 +1053,81 @@@ nouveau_bo_fence(struct nouveau_bo *nvb
        nouveau_fence_unref(&old_fence);
  }
  
 +static int
 +nouveau_ttm_tt_populate(struct ttm_tt *ttm)
 +{
 +      struct ttm_dma_tt *ttm_dma = (void *)ttm;
 +      struct drm_nouveau_private *dev_priv;
 +      struct drm_device *dev;
 +      unsigned i;
 +      int r;
 +
 +      if (ttm->state != tt_unpopulated)
 +              return 0;
 +
 +      dev_priv = nouveau_bdev(ttm->bdev);
 +      dev = dev_priv->dev;
 +
 +#ifdef CONFIG_SWIOTLB
 +      if (swiotlb_nr_tbl()) {
 +              return ttm_dma_populate((void *)ttm, dev->dev);
 +      }
 +#endif
 +
 +      r = ttm_pool_populate(ttm);
 +      if (r) {
 +              return r;
 +      }
 +
 +      for (i = 0; i < ttm->num_pages; i++) {
 +              ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i],
 +                                                 0, PAGE_SIZE,
 +                                                 PCI_DMA_BIDIRECTIONAL);
 +              if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) {
 +                      while (--i) {
 +                              pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
 +                                             PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 +                              ttm_dma->dma_address[i] = 0;
 +                      }
 +                      ttm_pool_unpopulate(ttm);
 +                      return -EFAULT;
 +              }
 +      }
 +      return 0;
 +}
 +
 +static void
 +nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
 +{
 +      struct ttm_dma_tt *ttm_dma = (void *)ttm;
 +      struct drm_nouveau_private *dev_priv;
 +      struct drm_device *dev;
 +      unsigned i;
 +
 +      dev_priv = nouveau_bdev(ttm->bdev);
 +      dev = dev_priv->dev;
 +
 +#ifdef CONFIG_SWIOTLB
 +      if (swiotlb_nr_tbl()) {
 +              ttm_dma_unpopulate((void *)ttm, dev->dev);
 +              return;
 +      }
 +#endif
 +
 +      for (i = 0; i < ttm->num_pages; i++) {
 +              if (ttm_dma->dma_address[i]) {
 +                      pci_unmap_page(dev->pdev, ttm_dma->dma_address[i],
 +                                     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 +              }
 +      }
 +
 +      ttm_pool_unpopulate(ttm);
 +}
 +
  struct ttm_bo_driver nouveau_bo_driver = {
 -      .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
 +      .ttm_tt_create = &nouveau_ttm_tt_create,
 +      .ttm_tt_populate = &nouveau_ttm_tt_populate,
 +      .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
        .invalidate_caches = nouveau_bo_invalidate_caches,
        .init_mem_type = nouveau_bo_init_mem_type,
        .evict_flags = nouveau_bo_evict_flags,
index 2531ef54c3e9fa60b5537c96ead8a5d87e59d8a8,b12fd2c80812d002e0840787e8ff47481a3691a2..7e88cd7f2b995c199dc856d63998327c07bf7fa0
@@@ -64,7 -64,7 +64,7 @@@ static const struct drm_framebuffer_fun
  int
  nouveau_framebuffer_init(struct drm_device *dev,
                         struct nouveau_framebuffer *nv_fb,
 -                       struct drm_mode_fb_cmd *mode_cmd,
 +                       struct drm_mode_fb_cmd2 *mode_cmd,
                         struct nouveau_bo *nvbo)
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
  
                if (!tile_flags) {
                        if (dev_priv->card_type < NV_D0)
 -                              nv_fb->r_pitch = 0x00100000 | fb->pitch;
 +                              nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
                        else
 -                              nv_fb->r_pitch = 0x01000000 | fb->pitch;
 +                              nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
                } else {
                        u32 mode = nvbo->tile_mode;
                        if (dev_priv->card_type >= NV_C0)
                                mode >>= 4;
 -                      nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode;
 +                      nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
                }
        }
  
  static struct drm_framebuffer *
  nouveau_user_framebuffer_create(struct drm_device *dev,
                                struct drm_file *file_priv,
 -                              struct drm_mode_fb_cmd *mode_cmd)
 +                              struct drm_mode_fb_cmd2 *mode_cmd)
  {
        struct nouveau_framebuffer *nouveau_fb;
        struct drm_gem_object *gem;
        int ret;
  
 -      gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
 +      gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
        if (!gem)
                return ERR_PTR(-ENOENT);
  
@@@ -294,7 -294,7 +294,7 @@@ nouveau_crtc_page_flip(struct drm_crtc 
        /* Initialize a page flip struct */
        *s = (struct nouveau_page_flip_state)
                { { }, event, nouveau_crtc(crtc)->index,
 -                fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
 +                fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,
                  new_bo->bo.offset };
  
        /* Choose the channel the flip will be handled in */
@@@ -369,3 -369,48 +369,48 @@@ nouveau_finish_page_flip(struct nouveau
        spin_unlock_irqrestore(&dev->event_lock, flags);
        return 0;
  }
+ int
+ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
+                           struct drm_mode_create_dumb *args)
+ {
+       struct nouveau_bo *bo;
+       int ret;
+       args->pitch = roundup(args->width * (args->bpp / 8), 256);
+       args->size = args->pitch * args->height;
+       args->size = roundup(args->size, PAGE_SIZE);
+       ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
+       if (ret)
+               return ret;
+       ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle);
+       drm_gem_object_unreference_unlocked(bo->gem);
+       return ret;
+ }
+ int
+ nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+                            uint32_t handle)
+ {
+       return drm_gem_handle_delete(file_priv, handle);
+ }
+ int
+ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
+                               struct drm_device *dev,
+                               uint32_t handle, uint64_t *poffset)
+ {
+       struct drm_gem_object *gem;
+       gem = drm_gem_object_lookup(dev, file_priv, handle);
+       if (gem) {
+               struct nouveau_bo *bo = gem->driver_private;
+               *poffset = bo->bo.addr_space_offset;
+               drm_gem_object_unreference_unlocked(gem);
+               return 0;
+       }
+       return -ENOENT;
+ }
index d661bc5e3945b7b7a73b7b34a536743185a5dff4,9791d13c9e3b8d9d223bd5bb1cae182de4bc89ee..f0a60afac446664422d5486d6379b4b5357880d0
@@@ -388,21 -388,6 +388,21 @@@ nouveau_pci_resume(struct pci_dev *pdev
        return 0;
  }
  
 +static const struct file_operations nouveau_driver_fops = {
 +      .owner = THIS_MODULE,
 +      .open = drm_open,
 +      .release = drm_release,
 +      .unlocked_ioctl = drm_ioctl,
 +      .mmap = nouveau_ttm_mmap,
 +      .poll = drm_poll,
 +      .fasync = drm_fasync,
 +      .read = drm_read,
 +#if defined(CONFIG_COMPAT)
 +      .compat_ioctl = nouveau_compat_ioctl,
 +#endif
 +      .llseek = noop_llseek,
 +};
 +
  static struct drm_driver driver = {
        .driver_features =
                DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
        .disable_vblank = nouveau_vblank_disable,
        .reclaim_buffers = drm_core_reclaim_buffers,
        .ioctls = nouveau_ioctls,
 -      .fops = {
 -              .owner = THIS_MODULE,
 -              .open = drm_open,
 -              .release = drm_release,
 -              .unlocked_ioctl = drm_ioctl,
 -              .mmap = nouveau_ttm_mmap,
 -              .poll = drm_poll,
 -              .fasync = drm_fasync,
 -              .read = drm_read,
 -#if defined(CONFIG_COMPAT)
 -              .compat_ioctl = nouveau_compat_ioctl,
 -#endif
 -              .llseek = noop_llseek,
 -      },
 -
 +      .fops = &nouveau_driver_fops,
        .gem_init_object = nouveau_gem_object_new,
        .gem_free_object = nouveau_gem_object_del,
        .gem_open_object = nouveau_gem_object_open,
        .gem_close_object = nouveau_gem_object_close,
  
+       .dumb_create = nouveau_display_dumb_create,
+       .dumb_map_offset = nouveau_display_dumb_map_offset,
+       .dumb_destroy = nouveau_display_dumb_destroy,
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
  #ifdef GIT_REVISION
index 0c53e39fc6c9c43a04f7872e06ee5496d2608983,4c0be3a4ed882f5430ea628ba4d80fef1f1d3690..dfddb7e078a1e84aa7f7c06479811a5599b02f74
@@@ -1000,10 -1000,7 +1000,10 @@@ extern int nouveau_sgdma_init(struct dr
  extern void nouveau_sgdma_takedown(struct drm_device *);
  extern uint32_t nouveau_sgdma_get_physical(struct drm_device *,
                                           uint32_t offset);
 -extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
 +extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
 +                                             unsigned long size,
 +                                             uint32_t page_flags,
 +                                             struct page *dummy_read_page);
  
  /* nouveau_debugfs.c */
  #if defined(CONFIG_DRM_NOUVEAU_DEBUG)
@@@ -1421,6 -1418,12 +1421,12 @@@ int nouveau_crtc_page_flip(struct drm_c
                           struct drm_pending_vblank_event *event);
  int nouveau_finish_page_flip(struct nouveau_channel *,
                             struct nouveau_page_flip_state *);
+ int nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
+                               struct drm_mode_create_dumb *args);
+ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
+                                   uint32_t handle, uint64_t *offset);
+ int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
+                                uint32_t handle);
  
  /* nv10_gpio.c */
  int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
index defffd140781b810fd12a2f079215eb506065e04,3a4cc32b9e44c44f92fab174792778def49197f4..dbb151834121c831a6a03975d7b37e1e2966cd64
@@@ -281,7 -281,7 +281,7 @@@ nouveau_fbcon_create(struct nouveau_fbd
        struct nouveau_framebuffer *nouveau_fb;
        struct nouveau_channel *chan;
        struct nouveau_bo *nvbo;
 -      struct drm_mode_fb_cmd mode_cmd;
 +      struct drm_mode_fb_cmd2 mode_cmd;
        struct pci_dev *pdev = dev->pdev;
        struct device *device = &pdev->dev;
        int size, ret;
        mode_cmd.width = sizes->surface_width;
        mode_cmd.height = sizes->surface_height;
  
 -      mode_cmd.bpp = sizes->surface_bpp;
 -      mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
 -      mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
 -      mode_cmd.depth = sizes->surface_depth;
 +      mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3);
 +      mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256);
  
 -      size = mode_cmd.pitch * mode_cmd.height;
 +      mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
 +                                                        sizes->surface_depth);
 +
 +      size = mode_cmd.pitches[0] * mode_cmd.height;
        size = roundup(size, PAGE_SIZE);
  
        ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
        info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
        info->screen_size = size;
  
 -      drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 +      drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height);
  
        /* Set aperture base/size for vesafb takeover */
@@@ -488,6 -487,7 +488,7 @@@ int nouveau_fbcon_init(struct drm_devic
  {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fbdev *nfbdev;
+       int preferred_bpp;
        int ret;
  
        nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
        }
  
        drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
-       drm_fb_helper_initial_config(&nfbdev->helper, 32);
+       if (dev_priv->vram_size <= 32 * 1024 * 1024)
+               preferred_bpp = 8;
+       else if (dev_priv->vram_size <= 64 * 1024 * 1024)
+               preferred_bpp = 16;
+       else
+               preferred_bpp = 32;
+       drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
        return 0;
  }
  
index 7567ff2510e00ab098bd11a966f1828bba7b95dd,2b97262e3ab14af5af32b4d85711828563450b09..457bbad3cbf9617042ee4982b2de2bed684549bd
@@@ -1107,9 -1107,40 +1107,40 @@@ static int dce4_crtc_do_set_base(struc
                return -EINVAL;
        }
  
-       if (tiling_flags & RADEON_TILING_MACRO)
+       if (tiling_flags & RADEON_TILING_MACRO) {
+               if (rdev->family >= CHIP_CAYMAN)
+                       tmp = rdev->config.cayman.tile_config;
+               else
+                       tmp = rdev->config.evergreen.tile_config;
+               switch ((tmp & 0xf0) >> 4) {
+               case 0: /* 4 banks */
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                       break;
+               case 1: /* 8 banks */
+               default:
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                       break;
+               case 2: /* 16 banks */
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                       break;
+               }
+               switch ((tmp & 0xf000) >> 12) {
+               case 0: /* 1KB rows */
+               default:
+                       fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB);
+                       break;
+               case 1: /* 2KB rows */
+                       fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB);
+                       break;
+               case 2: /* 4KB rows */
+                       fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB);
+                       break;
+               }
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-       else if (tiling_flags & RADEON_TILING_MICRO)
+       else if (tiling_flags & RADEON_TILING_MICRO)
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
  
        switch (radeon_crtc->crtc_id) {
        WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);
        WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);
  
 -      fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8);
 +      fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
        WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
        WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
  
@@@ -1322,7 -1353,7 +1353,7 @@@ static int avivo_crtc_do_set_base(struc
        WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);
        WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);
  
 -      fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8);
 +      fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
        WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
        WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
  
@@@ -1522,12 -1553,6 +1553,6 @@@ static bool atombios_crtc_mode_fixup(st
                                     struct drm_display_mode *mode,
                                     struct drm_display_mode *adjusted_mode)
  {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index 83b2e016a4a1babd53824abe48c1274df3bb3f6c,8227e76b5c70a1d1b97bcac741f1559272a2250e..c8f4dbd2d17ce1bed480a486263d87f40e41cdce
@@@ -320,6 -320,7 +320,6 @@@ struct radeon_gart 
        unsigned                        table_size;
        struct page                     **pages;
        dma_addr_t                      *pages_addr;
 -      bool                            *ttm_alloced;
        bool                            ready;
  };
  
@@@ -610,7 -611,8 +610,8 @@@ struct radeon_cs_parser 
        struct radeon_ib        *ib;
        void                    *track;
        unsigned                family;
-       int parser_error;
+       int                     parser_error;
+       bool                    keep_tiling_flags;
  };
  
  extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
@@@ -783,8 -785,7 +784,7 @@@ struct radeon_pm_clock_info 
  
  struct radeon_power_state {
        enum radeon_pm_state_type type;
-       /* XXX: use a define for num clock modes */
-       struct radeon_pm_clock_info clock_info[8];
+       struct radeon_pm_clock_info *clock_info;
        /* number of valid clock modes in this power state */
        int num_clock_modes;
        struct radeon_pm_clock_info *default_clock_mode;
@@@ -854,6 -855,9 +854,9 @@@ struct radeon_pm 
        struct device           *int_hwmon_dev;
  };
  
+ int radeon_pm_get_type_index(struct radeon_device *rdev,
+                            enum radeon_pm_state_type ps_type,
+                            int instance);
  
  /*
   * Benchmarking
@@@ -1141,6 -1145,48 +1144,48 @@@ struct r600_vram_scratch 
        u64                             gpu_addr;
  };
  
+ /*
+  * Mutex which allows recursive locking from the same process.
+  */
+ struct radeon_mutex {
+       struct mutex            mutex;
+       struct task_struct      *owner;
+       int                     level;
+ };
+ static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+ {
+       mutex_init(&mutex->mutex);
+       mutex->owner = NULL;
+       mutex->level = 0;
+ }
+ static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+ {
+       if (mutex_trylock(&mutex->mutex)) {
+               /* The mutex was unlocked before, so it's ours now */
+               mutex->owner = current;
+       } else if (mutex->owner != current) {
+               /* Another process locked the mutex, take it */
+               mutex_lock(&mutex->mutex);
+               mutex->owner = current;
+       }
+       /* Otherwise the mutex was already locked by this process */
+       mutex->level++;
+ }
+ static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+ {
+       if (--mutex->level > 0)
+               return;
+       mutex->owner = NULL;
+       mutex_unlock(&mutex->mutex);
+ }
  /*
   * Core structure, functions and helpers.
   */
@@@ -1196,7 -1242,7 +1241,7 @@@ struct radeon_device 
        struct radeon_gem               gem;
        struct radeon_pm                pm;
        uint32_t                        bios_scratch[RADEON_BIOS_NUM_SCRATCH];
-       struct mutex                    cs_mutex;
+       struct radeon_mutex             cs_mutex;
        struct radeon_wb                wb;
        struct radeon_dummy_page        dummy_page;
        bool                            gpu_lockup;
index 7c31321df45b1e80c7cddddb71afebb5337f56cb,c4d00a171411890fe701ea853ca084c39e4ac3b7..fb347a80486f51106054183b7bfaf56d54a90937
@@@ -716,7 -716,7 +716,7 @@@ int radeon_device_init(struct radeon_de
  
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
-       mutex_init(&rdev->cs_mutex);
+       radeon_mutex_init(&rdev->cs_mutex);
        mutex_init(&rdev->ib_pool.mutex);
        mutex_init(&rdev->cp.mutex);
        mutex_init(&rdev->dc_hw_i2c_mutex);
        r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
        if (r) {
                rdev->need_dma32 = true;
 +              dma_bits = 32;
                printk(KERN_WARNING "radeon: No suitable DMA available.\n");
        }
 +      r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
 +      if (r) {
 +              pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
 +              printk(KERN_WARNING "radeon: No coherent DMA available.\n");
 +      }
  
        /* Registers mapping */
        /* TODO: block userspace mapping of io register */
@@@ -961,6 -955,9 +961,9 @@@ int radeon_gpu_reset(struct radeon_devi
        int r;
        int resched;
  
+       /* Prevent CS ioctl from interfering */
+       radeon_mutex_lock(&rdev->cs_mutex);
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
                radeon_restore_bios_scratch_regs(rdev);
                drm_helper_resume_force_mode(rdev->ddev);
                ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-               return 0;
        }
-       /* bad news, how to tell it to userspace ? */
-       dev_info(rdev->dev, "GPU reset failed\n");
+       radeon_mutex_unlock(&rdev->cs_mutex);
+       if (r) {
+               /* bad news, how to tell it to userspace ? */
+               dev_info(rdev->dev, "GPU reset failed\n");
+       }
        return r;
  }
  
index e42c34b98c7b7efe776b75e944a971942064de53,71499fc3daf524f8b719692e9ff7aacb6219b2e9..c3ef1d266f88743f34a368549ec172dd908a8519
   *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
   *   2.10.0 - fusion 2D tiling
   *   2.11.0 - backend map, initial compute support for the CS checker
+  *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
   */
  #define KMS_DRIVER_MAJOR      2
- #define KMS_DRIVER_MINOR      11
+ #define KMS_DRIVER_MINOR      12
  #define KMS_DRIVER_PATCHLEVEL 0
  int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
  int radeon_driver_unload_kms(struct drm_device *dev);
@@@ -205,21 -206,6 +206,21 @@@ static struct pci_device_id pciidlist[
  MODULE_DEVICE_TABLE(pci, pciidlist);
  #endif
  
 +static const struct file_operations radeon_driver_old_fops = {
 +      .owner = THIS_MODULE,
 +      .open = drm_open,
 +      .release = drm_release,
 +      .unlocked_ioctl = drm_ioctl,
 +      .mmap = drm_mmap,
 +      .poll = drm_poll,
 +      .fasync = drm_fasync,
 +      .read = drm_read,
 +#ifdef CONFIG_COMPAT
 +      .compat_ioctl = radeon_compat_ioctl,
 +#endif
 +      .llseek = noop_llseek,
 +};
 +
  static struct drm_driver driver_old = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
        .reclaim_buffers = drm_core_reclaim_buffers,
        .ioctls = radeon_ioctls,
        .dma_ioctl = radeon_cp_buffers,
 -      .fops = {
 -               .owner = THIS_MODULE,
 -               .open = drm_open,
 -               .release = drm_release,
 -               .unlocked_ioctl = drm_ioctl,
 -               .mmap = drm_mmap,
 -               .poll = drm_poll,
 -               .fasync = drm_fasync,
 -               .read = drm_read,
 -#ifdef CONFIG_COMPAT
 -               .compat_ioctl = radeon_compat_ioctl,
 -#endif
 -               .llseek = noop_llseek,
 -      },
 -
 +      .fops = &radeon_driver_old_fops,
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = DRIVER_DATE,
@@@ -304,20 -304,6 +305,20 @@@ radeon_pci_resume(struct pci_dev *pdev
        return radeon_resume_kms(dev);
  }
  
 +static const struct file_operations radeon_driver_kms_fops = {
 +      .owner = THIS_MODULE,
 +      .open = drm_open,
 +      .release = drm_release,
 +      .unlocked_ioctl = drm_ioctl,
 +      .mmap = radeon_mmap,
 +      .poll = drm_poll,
 +      .fasync = drm_fasync,
 +      .read = drm_read,
 +#ifdef CONFIG_COMPAT
 +      .compat_ioctl = radeon_kms_compat_ioctl,
 +#endif
 +};
 +
  static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
        .dumb_create = radeon_mode_dumb_create,
        .dumb_map_offset = radeon_mode_dumb_mmap,
        .dumb_destroy = radeon_mode_dumb_destroy,
 -      .fops = {
 -               .owner = THIS_MODULE,
 -               .open = drm_open,
 -               .release = drm_release,
 -               .unlocked_ioctl = drm_ioctl,
 -               .mmap = radeon_mmap,
 -               .poll = drm_poll,
 -               .fasync = drm_fasync,
 -               .read = drm_read,
 -#ifdef CONFIG_COMPAT
 -               .compat_ioctl = radeon_kms_compat_ioctl,
 -#endif
 -      },
 -
 +      .fops = &radeon_driver_kms_fops,
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = DRIVER_DATE,
index 95b93604b6799b41c1c484fe8735d215ce0e25fd,daadf2111040875d93df8fef9752428dd35f1cae..25a19c483075650725d8bdb7a6af68ff993f1a5d
@@@ -437,7 -437,7 +437,7 @@@ int radeon_crtc_do_set_base(struct drm_
  
        crtc_offset_cntl = 0;
  
 -      pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8);
 +      pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
        crtc_pitch  = (((pitch_pixels * target_fb->bits_per_pixel) +
                        ((target_fb->bits_per_pixel * 8) - 1)) /
                       (target_fb->bits_per_pixel * 8));
@@@ -991,12 -991,6 +991,6 @@@ static bool radeon_crtc_mode_fixup(stru
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
  {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index 119b6e3ff9063ad5d8980f0bbf45efbd553be711,0bb0f5f713e6cf9166a1b91eb19ab81b85206716..2f0eab66ece6c1eb9eeffaae72a517727a0257ee
@@@ -137,7 -137,6 +137,7 @@@ static void ttm_bo_release_list(struct 
        struct ttm_buffer_object *bo =
            container_of(list_kref, struct ttm_buffer_object, list_kref);
        struct ttm_bo_device *bdev = bo->bdev;
 +      size_t acc_size = bo->acc_size;
  
        BUG_ON(atomic_read(&bo->list_kref.refcount));
        BUG_ON(atomic_read(&bo->kref.refcount));
        if (bo->destroy)
                bo->destroy(bo);
        else {
 -              ttm_mem_global_free(bdev->glob->mem_glob, bo->acc_size);
                kfree(bo);
        }
 +      ttm_mem_global_free(bdev->glob->mem_glob, acc_size);
  }
  
  int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible)
@@@ -338,11 -337,27 +338,11 @@@ static int ttm_bo_add_ttm(struct ttm_bu
                if (zero_alloc)
                        page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
        case ttm_bo_type_kernel:
 -              bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
 -                                      page_flags, glob->dummy_read_page);
 +              bo->ttm = bdev->driver->ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
 +                                                    page_flags, glob->dummy_read_page);
                if (unlikely(bo->ttm == NULL))
                        ret = -ENOMEM;
                break;
 -      case ttm_bo_type_user:
 -              bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
 -                                      page_flags | TTM_PAGE_FLAG_USER,
 -                                      glob->dummy_read_page);
 -              if (unlikely(bo->ttm == NULL)) {
 -                      ret = -ENOMEM;
 -                      break;
 -              }
 -
 -              ret = ttm_tt_set_user(bo->ttm, current,
 -                                    bo->buffer_start, bo->num_pages);
 -              if (unlikely(ret != 0)) {
 -                      ttm_tt_destroy(bo->ttm);
 -                      bo->ttm = NULL;
 -              }
 -              break;
        default:
                printk(KERN_ERR TTM_PFX "Illegal buffer object type\n");
                ret = -EINVAL;
@@@ -404,6 -419,9 +404,6 @@@ static int ttm_bo_handle_move_mem(struc
                }
        }
  
 -      if (bdev->driver->move_notify)
 -              bdev->driver->move_notify(bo, mem);
 -
        if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
            !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
                ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem);
        if (ret)
                goto out_err;
  
 +      if (bdev->driver->move_notify)
 +              bdev->driver->move_notify(bo, mem);
 +
  moved:
        if (bo->evicted) {
                ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
@@@ -457,9 -472,6 +457,9 @@@ out_err
  
  static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
  {
 +      if (bo->bdev->driver->move_notify)
 +              bo->bdev->driver->move_notify(bo, NULL);
 +
        if (bo->ttm) {
                ttm_tt_unbind(bo->ttm);
                ttm_tt_destroy(bo->ttm);
@@@ -562,10 -574,16 +562,16 @@@ retry
                return ret;
  
        spin_lock(&glob->lru_lock);
+       if (unlikely(list_empty(&bo->ddestroy))) {
+               spin_unlock(&glob->lru_lock);
+               return 0;
+       }
        ret = ttm_bo_reserve_locked(bo, interruptible,
                                    no_wait_reserve, false, 0);
  
-       if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
+       if (unlikely(ret != 0)) {
                spin_unlock(&glob->lru_lock);
                return ret;
        }
@@@ -895,12 -913,16 +901,12 @@@ static uint32_t ttm_bo_select_caching(s
  }
  
  static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
 -                               bool disallow_fixed,
                                 uint32_t mem_type,
                                 uint32_t proposed_placement,
                                 uint32_t *masked_placement)
  {
        uint32_t cur_flags = ttm_bo_type_flags(mem_type);
  
 -      if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed)
 -              return false;
 -
        if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0)
                return false;
  
@@@ -945,6 -967,7 +951,6 @@@ int ttm_bo_mem_space(struct ttm_buffer_
                man = &bdev->man[mem_type];
  
                type_ok = ttm_bo_mt_compatible(man,
 -                                              bo->type == ttm_bo_type_user,
                                                mem_type,
                                                placement->placement[i],
                                                &cur_flags);
                if (!man->has_type)
                        continue;
                if (!ttm_bo_mt_compatible(man,
 -                                              bo->type == ttm_bo_type_user,
                                                mem_type,
                                                placement->busy_placement[i],
                                                &cur_flags))
@@@ -1161,17 -1185,6 +1167,17 @@@ int ttm_bo_init(struct ttm_bo_device *b
  {
        int ret = 0;
        unsigned long num_pages;
 +      struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
 +
 +      ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
 +      if (ret) {
 +              printk(KERN_ERR TTM_PFX "Out of kernel memory.\n");
 +              if (destroy)
 +                      (*destroy)(bo);
 +              else
 +                      kfree(bo);
 +              return -ENOMEM;
 +      }
  
        size += buffer_start & ~PAGE_MASK;
        num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@@ -1242,34 -1255,14 +1248,34 @@@ out_err
  }
  EXPORT_SYMBOL(ttm_bo_init);
  
 -static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
 -                               unsigned long num_pages)
 +size_t ttm_bo_acc_size(struct ttm_bo_device *bdev,
 +                     unsigned long bo_size,
 +                     unsigned struct_size)
  {
 -      size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) &
 -          PAGE_MASK;
 +      unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT;
 +      size_t size = 0;
  
 -      return glob->ttm_bo_size + 2 * page_array_size;
 +      size += ttm_round_pot(struct_size);
 +      size += PAGE_ALIGN(npages * sizeof(void *));
 +      size += ttm_round_pot(sizeof(struct ttm_tt));
 +      return size;
  }
 +EXPORT_SYMBOL(ttm_bo_acc_size);
 +
 +size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev,
 +                         unsigned long bo_size,
 +                         unsigned struct_size)
 +{
 +      unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT;
 +      size_t size = 0;
 +
 +      size += ttm_round_pot(struct_size);
 +      size += PAGE_ALIGN(npages * sizeof(void *));
 +      size += PAGE_ALIGN(npages * sizeof(dma_addr_t));
 +      size += ttm_round_pot(sizeof(struct ttm_dma_tt));
 +      return size;
 +}
 +EXPORT_SYMBOL(ttm_bo_dma_acc_size);
  
  int ttm_bo_create(struct ttm_bo_device *bdev,
                        unsigned long size,
  {
        struct ttm_buffer_object *bo;
        struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
 +      size_t acc_size;
        int ret;
  
 -      size_t acc_size =
 -          ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
 +      acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object));
        ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
        if (unlikely(ret != 0))
                return ret;
@@@ -1472,6 -1465,13 +1478,6 @@@ int ttm_bo_global_init(struct drm_globa
                goto out_no_shrink;
        }
  
 -      glob->ttm_bo_extra_size =
 -              ttm_round_pot(sizeof(struct ttm_tt)) +
 -              ttm_round_pot(sizeof(struct ttm_backend));
 -
 -      glob->ttm_bo_size = glob->ttm_bo_extra_size +
 -              ttm_round_pot(sizeof(struct ttm_buffer_object));
 -
        atomic_set(&glob->bo_count, 0);
  
        ret = kobject_init_and_add(
index 0585987f2945f6dcc1d0729093ab249d6bc29e13,37d40545ed77347007d1051689895d40b116cd1d..1748a7142aca76811ab6fff8b4dbcf921496737b
@@@ -105,6 -105,10 +105,10 @@@ int vmw_du_crtc_cursor_set(struct drm_c
        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);
@@@ -410,8 -414,9 +414,9 @@@ static int do_surface_dirty_sou(struct 
        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);
@@@ -605,7 -610,7 +610,7 @@@ static int vmw_kms_new_framebuffer_surf
  
        /* XXX get the first 3 from the surface info */
        vfbs->base.base.bits_per_pixel = mode_cmd->bpp;
 -      vfbs->base.base.pitch = mode_cmd->pitch;
 +      vfbs->base.base.pitches[0] = mode_cmd->pitch;
        vfbs->base.base.depth = mode_cmd->depth;
        vfbs->base.base.width = mode_cmd->width;
        vfbs->base.base.height = mode_cmd->height;
@@@ -719,7 -724,7 +724,7 @@@ static int do_dmabuf_define_gmrfb(struc
        cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel;
        cmd->body.format.colorDepth = depth;
        cmd->body.format.reserved = 0;
 -      cmd->body.bytesPerLine = framebuffer->base.pitch;
 +      cmd->body.bytesPerLine = framebuffer->base.pitches[0];
        cmd->body.ptr.gmrId = framebuffer->user_handle;
        cmd->body.ptr.offset = 0;
  
@@@ -961,7 -966,7 +966,7 @@@ static int vmw_kms_new_framebuffer_dmab
        }
  
        vfbd->base.base.bits_per_pixel = mode_cmd->bpp;
 -      vfbd->base.base.pitch = mode_cmd->pitch;
 +      vfbd->base.base.pitches[0] = mode_cmd->pitch;
        vfbd->base.base.depth = mode_cmd->depth;
        vfbd->base.base.width = mode_cmd->width;
        vfbd->base.base.height = mode_cmd->height;
@@@ -990,7 -995,7 +995,7 @@@ out_err1
  
  static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
                                                 struct drm_file *file_priv,
 -                                               struct drm_mode_fb_cmd *mode_cmd)
 +                                               struct drm_mode_fb_cmd2 *mode_cmd2)
  {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
        struct vmw_surface *surface = NULL;
        struct vmw_dma_buffer *bo = NULL;
        struct ttm_base_object *user_obj;
 +      struct drm_mode_fb_cmd mode_cmd;
        u64 required_size;
        int ret;
  
 +      mode_cmd.width = mode_cmd2->width;
 +      mode_cmd.height = mode_cmd2->height;
 +      mode_cmd.pitch = mode_cmd2->pitches[0];
 +      mode_cmd.handle = mode_cmd2->handles[0];
 +      drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
 +                                  &mode_cmd.bpp);
 +
        /**
         * This code should be conditioned on Screen Objects not being used.
         * If screen objects are used, we can allocate a GMR to hold the
         * requested framebuffer.
         */
  
 -      required_size = mode_cmd->pitch * mode_cmd->height;
 +      required_size = mode_cmd.pitch * mode_cmd.height;
        if (unlikely(required_size > (u64) dev_priv->vram_size)) {
                DRM_ERROR("VRAM size is too small for requested mode.\n");
                return ERR_PTR(-ENOMEM);
         * command stream using user-space handles.
         */
  
 -      user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle);
 +      user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
        if (unlikely(user_obj == NULL)) {
                DRM_ERROR("Could not locate requested kms frame buffer.\n");
                return ERR_PTR(-ENOENT);
         */
  
        ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
 -                                           mode_cmd->handle, &surface);
 +                                           mode_cmd.handle, &surface);
        if (ret)
                goto try_dmabuf;
  
                goto err_not_scanout;
  
        ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface,
 -                                            &vfb, mode_cmd);
 +                                            &vfb, &mode_cmd);
  
        /* vmw_user_surface_lookup takes one ref so does new_fb */
        vmw_surface_unreference(&surface);
  try_dmabuf:
        DRM_INFO("%s: trying buffer\n", __func__);
  
 -      ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
 +      ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo);
        if (ret) {
                DRM_ERROR("failed to find buffer: %i\n", ret);
                return ERR_PTR(-ENOENT);
        }
  
        ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
 -                                           mode_cmd);
 +                                           &mode_cmd);
  
        /* vmw_user_dmabuf_lookup takes one ref so does new_fb */
        vmw_dmabuf_unreference(&bo);
@@@ -1243,7 -1240,7 +1248,7 @@@ int vmw_kms_readback(struct vmw_privat
        cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel;
        cmd->body.format.colorDepth = vfb->base.depth;
        cmd->body.format.reserved = 0;
 -      cmd->body.bytesPerLine = vfb->base.pitch;
 +      cmd->body.bytesPerLine = vfb->base.pitches[0];
        cmd->body.ptr.gmrId = vfb->user_handle;
        cmd->body.ptr.offset = 0;
  
@@@ -1331,7 -1328,10 +1336,10 @@@ int vmw_kms_close(struct vmw_private *d
         * 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;
  }
  
@@@ -1809,7 -1809,8 +1817,8 @@@ int vmw_kms_update_layout_ioctl(struct 
        }
  
        rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
-       rects = kzalloc(rects_size, GFP_KERNEL);
+       rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect),
+                       GFP_KERNEL);
        if (unlikely(!rects)) {
                ret = -ENOMEM;
                goto out_unlock;
        }
  
        for (i = 0; i < arg->num_outputs; ++i) {
-               if (rects->x < 0 ||
-                   rects->y < 0 ||
-                   rects->x + rects->w > mode_config->max_width ||
-                   rects->y + rects->h > mode_config->max_height) {
+               if (rects[i].x < 0 ||
+                   rects[i].y < 0 ||
+                   rects[i].x + rects[i].w > mode_config->max_width ||
+                   rects[i].y + rects[i].h > mode_config->max_height) {
                        DRM_ERROR("Invalid GUI layout.\n");
                        ret = -EINVAL;
                        goto out_free;
index 4864e5d72e72c7ee7ca20992bfc6b7635b67536c,284798aaf8b1391fd8d4de7e43bff52e5721272d..19e6a2041371c0fe9a908c71ac5c83cdbad3c015
@@@ -153,7 -153,7 +153,7 @@@ void __init xen_swiotlb_init(int verbos
        char *m = NULL;
        unsigned int repeat = 3;
  
 -      nr_tbl = swioltb_nr_tbl();
 +      nr_tbl = swiotlb_nr_tbl();
        if (nr_tbl)
                xen_io_tlb_nslabs = nr_tbl;
        else {
@@@ -166,7 -166,7 +166,7 @@@ retry
        /*
         * Get IO TLB memory from any location.
         */
-       xen_io_tlb_start = alloc_bootmem(bytes);
+       xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes));
        if (!xen_io_tlb_start) {
                m = "Cannot allocate Xen-SWIOTLB buffer!\n";
                goto error;
                               bytes,
                               xen_io_tlb_nslabs);
        if (rc) {
-               free_bootmem(__pa(xen_io_tlb_start), bytes);
+               free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes));
                m = "Failed to get contiguous memory for DMA from Xen!\n"\
                    "You either: don't have the permissions, do not have"\
                    " enough free memory under 4GB, or the hypervisor memory"\
diff --combined include/drm/drmP.h
index 1f630a5d75b46056023727b4901904737f10e3f1,1f9e9516e2b75da38aa87abbf774d1505803cc98..ecd5984ef6896254e3a1609cb38f99c99ad1eb9c
@@@ -918,7 -918,7 +918,7 @@@ struct drm_driver 
        int dev_priv_size;
        struct drm_ioctl_desc *ioctls;
        int num_ioctls;
 -      struct file_operations fops;
 +      const struct file_operations *fops;
        union {
                struct pci_driver *pci;
                struct platform_device *platform_device;
@@@ -990,7 -990,9 +990,9 @@@ struct drm_minor 
        struct proc_dir_entry *proc_root;  /**< proc directory entry */
        struct drm_info_node proc_nodes;
        struct dentry *debugfs_root;
-       struct drm_info_node debugfs_nodes;
+       struct list_head debugfs_list;
+       struct mutex debugfs_lock; /* Protects debugfs_list. */
  
        struct drm_master *master; /* currently active master for this node */
        struct list_head master_list;
diff --combined include/drm/drm_mode.h
index 966fe7daec6f57bc3087ac8a8c121f64d5253e3f,ddd46db65b57257164f13d703186bb7da5e7bb3a..2a2acda8b437089222a6b1d1cad4aaed6d08ddbe
@@@ -120,48 -120,11 +120,48 @@@ struct drm_mode_crtc 
        struct drm_mode_modeinfo mode;
  };
  
 -#define DRM_MODE_ENCODER_NONE  0
 -#define DRM_MODE_ENCODER_DAC   1
 -#define DRM_MODE_ENCODER_TMDS  2
 -#define DRM_MODE_ENCODER_LVDS  3
 -#define DRM_MODE_ENCODER_TVDAC         4
 +#define DRM_MODE_PRESENT_TOP_FIELD    (1<<0)
 +#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1)
 +
 +/* Planes blend with or override other bits on the CRTC */
 +struct drm_mode_set_plane {
 +      __u32 plane_id;
 +      __u32 crtc_id;
 +      __u32 fb_id; /* fb object contains surface format type */
 +      __u32 flags; /* see above flags */
 +
 +      /* Signed dest location allows it to be partially off screen */
 +      __s32 crtc_x, crtc_y;
 +      __u32 crtc_w, crtc_h;
 +
 +      /* Source values are 16.16 fixed point */
 +      __u32 src_x, src_y;
 +      __u32 src_h, src_w;
 +};
 +
 +struct drm_mode_get_plane {
 +      __u32 plane_id;
 +
 +      __u32 crtc_id;
 +      __u32 fb_id;
 +
 +      __u32 possible_crtcs;
 +      __u32 gamma_size;
 +
 +      __u32 count_format_types;
 +      __u64 format_type_ptr;
 +};
 +
 +struct drm_mode_get_plane_res {
 +      __u64 plane_id_ptr;
 +      __u32 count_planes;
 +};
 +
 +#define DRM_MODE_ENCODER_NONE 0
 +#define DRM_MODE_ENCODER_DAC  1
 +#define DRM_MODE_ENCODER_TMDS 2
 +#define DRM_MODE_ENCODER_LVDS 3
 +#define DRM_MODE_ENCODER_TVDAC        4
  #define DRM_MODE_ENCODER_VIRTUAL 5
  
  struct drm_mode_get_encoder {
@@@ -268,37 -231,12 +268,39 @@@ struct drm_mode_fb_cmd 
        __u32 handle;
  };
  
 +#define DRM_MODE_FB_INTERLACED        (1<<0) /* for interlaced framebuffers */
 +
 +struct drm_mode_fb_cmd2 {
 +      __u32 fb_id;
 +      __u32 width, height;
 +      __u32 pixel_format; /* fourcc code from drm_fourcc.h */
 +      __u32 flags; /* see above flags */
 +
 +      /*
 +       * In case of planar formats, this ioctl allows up to 4
 +       * buffer objects with offets and pitches per plane.
 +       * The pitch and offset order is dictated by the fourcc,
 +       * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as:
 +       *
 +       *   YUV 4:2:0 image with a plane of 8 bit Y samples
 +       *   followed by an interleaved U/V plane containing
 +       *   8 bit 2x2 subsampled colour difference samples.
 +       *
 +       * So it would consist of Y as offset[0] and UV as
 +       * offeset[1].  Note that offset[0] will generally
 +       * be 0.
 +       */
 +      __u32 handles[4];
 +      __u32 pitches[4]; /* pitch for each plane */
 +      __u32 offsets[4]; /* offset of each plane */
 +};
 +
  #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
  #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
  #define DRM_MODE_FB_DIRTY_FLAGS         0x03
  
+ #define DRM_MODE_FB_DIRTY_MAX_CLIPS     256
  /*
   * Mark a region of a framebuffer as dirty.
   *