Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101
authorAlan Hourihane <alanh@tungstengraphics.com>
Tue, 16 Oct 2007 14:28:33 +0000 (15:28 +0100)
committerAlan Hourihane <alanh@tungstengraphics.com>
Tue, 16 Oct 2007 14:28:33 +0000 (15:28 +0100)
Conflicts:

linux-core/drm_bo.c
linux-core/drm_objects.h
shared-core/i915_dma.c
shared-core/i915_drv.h

15 files changed:
1  2 
linux-core/Makefile.kernel
linux-core/drmP.h
linux-core/drm_bo.c
linux-core/drm_bo_move.c
linux-core/drm_compat.h
linux-core/drm_drv.c
linux-core/drm_fops.c
linux-core/drm_objects.h
linux-core/i915_buffer.c
linux-core/i915_fence.c
shared-core/drm.h
shared-core/i915_dma.c
shared-core/i915_drm.h
shared-core/i915_drv.h
shared-core/i915_irq.c

@@@ -20,10 -19,9 +20,10 @@@ r128-objs   := r128_drv.o r128_cce.o r1
  mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
  i810-objs   := i810_drv.o i810_dma.o
  i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
 -              i915_buffer.o
 +              i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \
 +              intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o
  nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
-               nouveau_object.o nouveau_irq.o nouveau_notifier.o \
+               nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
                nouveau_sgdma.o nouveau_dma.o \
                nv04_timer.o \
                nv04_mc.o nv40_mc.o nv50_mc.o \
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -263,9 -263,7 +263,8 @@@ static int drm_open_helper(struct inod
        priv->lock_count = 0;
  
        INIT_LIST_HEAD(&priv->lhead);
-       INIT_LIST_HEAD(&priv->user_objects);
        INIT_LIST_HEAD(&priv->refd_objects);
 +      INIT_LIST_HEAD(&priv->fbs);
  
        for (i=0; i<_DRM_NO_REF_TYPES; ++i) {
                ret = drm_ht_create(&priv->refd_object_hash[i], DRM_FILE_HASH_ORDER);
@@@ -451,6 -468,6 +467,7 @@@ extern int drm_bo_destroy_ioctl(struct 
  extern int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
++extern int drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, int pin);
  extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
  extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
@@@ -514,16 -541,70 +541,74 @@@ extern int drm_bo_move_accel_cleanup(st
                                     uint32_t fence_type,
                                     uint32_t fence_flags,
                                     struct drm_bo_mem_reg * new_mem);
+ extern int drm_bo_same_page(unsigned long offset, unsigned long offset2);
+ extern unsigned long drm_bo_offset_end(unsigned long offset,
+                                      unsigned long end);
+ struct drm_bo_kmap_obj {
+       void *virtual;
+       struct page *page;
+       enum {
+               bo_map_iomap,
+               bo_map_vmap,
+               bo_map_kmap,
+               bo_map_premapped,
+       } bo_kmap_type;
+ };
+ static inline void *drm_bmo_virtual(struct drm_bo_kmap_obj *map, int *is_iomem)
+ {
+       *is_iomem = (map->bo_kmap_type == bo_map_iomap ||
+                    map->bo_kmap_type == bo_map_premapped);
+       return map->virtual;
+ }
+ extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
+ extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
+                      unsigned long num_pages, struct drm_bo_kmap_obj *map);
  
- extern int drm_mem_reg_ioremap(struct drm_device *dev,
-                              struct drm_bo_mem_reg *mem, void **virtual);
- extern void drm_mem_reg_iounmap(struct drm_device *dev,
-                               struct drm_bo_mem_reg *mem, void *virtual);
+ /*
+  * drm_regman.c
+  */
+ struct drm_reg {
+       struct list_head head;
+       struct drm_fence_object *fence;
+       uint32_t fence_type;
+       uint32_t new_fence_type;
+ };
+ struct drm_reg_manager {
+       struct list_head free;
+       struct list_head lru;
+       struct list_head unfenced;
+       int (*reg_reusable)(const struct drm_reg *reg, const void *data);
+       void (*reg_destroy)(struct drm_reg *reg);
+ };
+ extern int drm_regs_alloc(struct drm_reg_manager *manager,
+                         const void *data,
+                         uint32_t fence_class,
+                         uint32_t fence_type,
+                         int interruptible,
+                         int no_wait,
+                         struct drm_reg **reg);
+ extern void drm_regs_fence(struct drm_reg_manager *regs,
+                          struct drm_fence_object *fence);
+ extern void drm_regs_free(struct drm_reg_manager *manager);
+ extern void drm_regs_add(struct drm_reg_manager *manager, struct drm_reg *reg);
+ extern void drm_regs_init(struct drm_reg_manager *manager,
+                         int (*reg_reusable)(const struct drm_reg *,
+                                             const void *),
+                         void (*reg_destroy)(struct drm_reg *));
  
 +extern int drm_mem_reg_ioremap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
 +                             void **virtual);
 +extern void drm_mem_reg_iounmap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
 +                              void *virtual);
  #ifdef CONFIG_DEBUG_MUTEXES
  #define DRM_ASSERT_LOCKED(_mutex)                                     \
        BUG_ON(!mutex_is_locked(_mutex) ||                              \
@@@ -84,8 -87,9 +87,9 @@@ int i915_init_mem_type(struct drm_devic
                man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
                    _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP;
                man->drm_bus_maptype = _DRM_AGP;
+               man->gpu_offset = 0;
                break;
 -      case DRM_BO_MEM_PRIV0:
 +      case DRM_BO_MEM_VRAM:
                if (!(drm_core_has_AGP(dev) && dev->agp)) {
                        DRM_ERROR("AGP is not enabled for memory type %u\n",
                                  (unsigned)type);
                man->flags =  _DRM_FLAG_MEMTYPE_MAPPABLE |
                    _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP;
                man->drm_bus_maptype = _DRM_AGP;
+               man->gpu_offset = 0;
                break;
 +      case DRM_BO_MEM_PRIV0: /* for OS preallocated space */
 +              DRM_ERROR("PRIV0 not used yet.\n");
 +              break;
        default:
                DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
                return -EINVAL;
@@@ -40,9 -40,9 +40,9 @@@
  
  static void i915_perform_flush(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 +      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        struct drm_fence_manager *fm = &dev->fm;
-       struct drm_fence_class_manager *fc = &fm->class[0];
+       struct drm_fence_class_manager *fc = &fm->fence_class[0];
        struct drm_fence_driver *driver = dev->driver->fence_driver;
        uint32_t flush_flags = 0;
        uint32_t flush_sequence = 0;
Simple merge
@@@ -694,9 -729,346 +698,346 @@@ static int i915_cmdbuffer(struct drm_de
        return 0;
  }
  
 -      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ #ifdef I915_HAVE_BUFFER
+ struct i915_relocatee_info {
+       struct drm_buffer_object *buf;
+       unsigned long offset;
+       u32 *data_page;
+       unsigned page_offset;
+       struct drm_bo_kmap_obj kmap;
+       int is_iomem;
+ };
+ static void i915_dereference_buffers_locked(struct drm_buffer_object **buffers,
+                                           unsigned num_buffers)
+ {
+       while (num_buffers--)
+               drm_bo_usage_deref_locked(&buffers[num_buffers]);
+ }
+ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
+                    struct drm_buffer_object **buffers,
+                    struct i915_relocatee_info *relocatee,
+                    uint32_t *reloc)
+ {
+       unsigned index;
+       unsigned long new_cmd_offset;
+       u32 val;
+       int ret;
+       if (reloc[2] >= num_buffers) {
+               DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]);
+               return -EINVAL;
+       }
+       new_cmd_offset = reloc[0];
+       if (!relocatee->data_page ||
+           !drm_bo_same_page(relocatee->offset, new_cmd_offset)) {
+               drm_bo_kunmap(&relocatee->kmap);
+               relocatee->offset = new_cmd_offset;
+               ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
+                                 1, &relocatee->kmap);
+               if (ret) {
+                       DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset);
+                       return ret;
+               }
+               relocatee->data_page = drm_bmo_virtual(&relocatee->kmap,
+                                                      &relocatee->is_iomem);
+               relocatee->page_offset = (relocatee->offset & PAGE_MASK);
+       }
+       val = buffers[reloc[2]]->offset;
+       index = (reloc[0] - relocatee->page_offset) >> 2;
+       /* add in validate */
+       val = val + reloc[1];
+       relocatee->data_page[index] = val;
+       return 0;
+ }
+ int i915_process_relocs(struct drm_file *file_priv,
+                       uint32_t buf_handle,
+                       uint32_t *reloc_buf_handle,
+                       struct i915_relocatee_info *relocatee,
+                       struct drm_buffer_object **buffers,
+                       uint32_t num_buffers)
+ {
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *reloc_list_object;
+       uint32_t cur_handle = *reloc_buf_handle;
+       uint32_t *reloc_page;
+       int ret, reloc_is_iomem, reloc_stride;
+       uint32_t num_relocs, reloc_offset, reloc_end, reloc_page_offset, next_offset, cur_offset;
+       struct drm_bo_kmap_obj reloc_kmap;
+       memset(&reloc_kmap, 0, sizeof(reloc_kmap));
+       reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1);
+       if (!reloc_list_object)
+               return -EINVAL;
+       ret = drm_bo_kmap(reloc_list_object, 0, 1, &reloc_kmap);
+       if (ret) {
+               DRM_ERROR("Could not map relocation buffer.\n");
+               goto out;
+       }
+       reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
+       num_relocs = reloc_page[0] & 0xffff;
+       if ((reloc_page[0] >> 16) & 0xffff) {
+               DRM_ERROR("Unsupported relocation type requested\n");
+               goto out;
+       }
+       /* get next relocate buffer handle */
+       *reloc_buf_handle = reloc_page[1];
+       reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */
+       DRM_DEBUG("num relocs is %d, next is %08X\n", num_relocs, reloc_page[1]);
+       reloc_page_offset = 0;
+       reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t);
+       reloc_end = reloc_offset + (num_relocs * reloc_stride);
+       do {
+               next_offset = drm_bo_offset_end(reloc_offset, reloc_end);
+               do {
+                       cur_offset = ((reloc_offset + reloc_page_offset) & ~PAGE_MASK) / sizeof(uint32_t);
+                       ret = i915_apply_reloc(file_priv, num_buffers,
+                                        buffers, relocatee, &reloc_page[cur_offset]);
+                       if (ret)
+                               goto out;
+                       reloc_offset += reloc_stride;
+               } while (reloc_offset < next_offset);
+               drm_bo_kunmap(&reloc_kmap);
+               reloc_offset = next_offset;
+               if (reloc_offset != reloc_end) {
+                       ret = drm_bo_kmap(reloc_list_object, reloc_offset >> PAGE_SHIFT, 1, &reloc_kmap);
+                       if (ret) {
+                               DRM_ERROR("Could not map relocation buffer.\n");
+                               goto out;
+                       }
+                       reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
+                       reloc_page_offset = reloc_offset & ~PAGE_MASK;
+               }
+       } while (reloc_offset != reloc_end);
+ out:
+       drm_bo_kunmap(&reloc_kmap);
+       mutex_lock(&dev->struct_mutex);
+       drm_bo_usage_deref_locked(&reloc_list_object);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+ }
+ /*
+  * Validate, add fence and relocate a block of bos from a userspace list
+  */
+ int i915_validate_buffer_list(struct drm_file *file_priv,
+                             unsigned int fence_class, uint64_t data,
+                             struct drm_buffer_object **buffers,
+                             uint32_t *num_buffers)
+ {
+       struct drm_i915_op_arg arg;
+       struct drm_bo_op_req *req = &arg.d.req;
+       struct drm_bo_arg_rep rep;
+       unsigned long next = 0;
+       int ret = 0;
+       unsigned buf_count = 0;
+       struct drm_device *dev = file_priv->head->dev;
+       uint32_t buf_reloc_handle, buf_handle;
+       struct i915_relocatee_info relocatee;
+       do {
+               if (buf_count >= *num_buffers) {
+                       DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers);
+                       ret = -EINVAL;
+                       goto out_err;
+               }
+               buffers[buf_count] = NULL;
+               if (copy_from_user(&arg, (void __user *)(unsigned)data, sizeof(arg))) {
+                       ret = -EFAULT;
+                       goto out_err;
+               }
+               if (arg.handled) {
+                       data = arg.next;
+                       buffers[buf_count] = drm_lookup_buffer_object(file_priv, req->arg_handle, 1);
+                       buf_count++;
+                       continue;
+               }
+               rep.ret = 0;
+               if (req->op != drm_bo_validate) {
+                       DRM_ERROR
+                           ("Buffer object operation wasn't \"validate\".\n");
+                       rep.ret = -EINVAL;
+                       goto out_err;
+               }
+               buf_handle = req->bo_req.handle;
+               buf_reloc_handle = arg.reloc_handle;
+               rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
+                                                req->bo_req.fence_class,
+                                                req->bo_req.flags,
+                                                req->bo_req.mask,
+                                                req->bo_req.hint,
+                                                &rep.bo_info,
+                                                &buffers[buf_count]);
+               if (rep.ret) {
+                       DRM_ERROR("error on handle validate %d\n", rep.ret);
+                       goto out_err;
+               }
+               next = arg.next;
+               arg.handled = 1;
+               arg.d.rep = rep;
+               if (copy_to_user((void __user *)(unsigned)data, &arg, sizeof(arg)))
+                       return -EFAULT;
+               data = next;
+               buf_count++;
+               if (buf_reloc_handle) {
+                       memset(&relocatee, 0, sizeof(relocatee));
+                       relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1);
+                       if (!relocatee.buf) {
+                               DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle);
+                               ret = -EINVAL;
+                               goto out_err;
+                       }
+                       while (buf_reloc_handle) {
+                               ret = i915_process_relocs(file_priv, buf_handle, &buf_reloc_handle, &relocatee, buffers, buf_count);
+                               if (ret) {
+                                       DRM_ERROR("process relocs failed\n");
+                                       break;
+                               }
+                       }
+                       drm_bo_kunmap(&relocatee.kmap);
+                       mutex_lock(&dev->struct_mutex);
+                       drm_bo_usage_deref_locked(&relocatee.buf);
+                       mutex_unlock(&dev->struct_mutex);
+                       if (ret)
+                               goto out_err;
+               }
+       } while (next != 0);
+       *num_buffers = buf_count;
+       return 0;
+ out_err:
+       mutex_lock(&dev->struct_mutex);
+       i915_dereference_buffers_locked(buffers, buf_count);
+       mutex_unlock(&dev->struct_mutex);
+       *num_buffers = 0;
+       return (ret) ? ret : rep.ret;
+ }
+ static int i915_execbuffer(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+ {
 -      struct _drm_i915_batchbuffer *batch = &exec_buf->batch;
++      struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+               dev_priv->sarea_priv;
+       struct drm_i915_execbuffer *exec_buf = data;
 -static int i915_do_cleanup_pageflip(struct drm_device * dev)
++      struct drm_i915_batchbuffer *batch = &exec_buf->batch;
+       struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
+       int num_buffers;
+       int ret;
+       struct drm_buffer_object **buffers;
+       struct drm_fence_object *fence;
+       if (!dev_priv->allow_batchbuffer) {
+               DRM_ERROR("Batchbuffer ioctl disabled\n");
+               return -EINVAL;
+       }
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
+                                                       batch->num_cliprects *
+                                                       sizeof(struct drm_clip_rect)))
+               return -EFAULT;
+       if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
+               return -EINVAL;
+       num_buffers = exec_buf->num_buffers;
+       buffers = drm_calloc(num_buffers, sizeof(struct drm_buffer_object *), DRM_MEM_DRIVER);
+       if (!buffers)
+               return -ENOMEM;
+       /* validate buffer list + fixup relocations */
+       ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
+                                       buffers, &num_buffers);
+       if (ret)
+               goto out_free;
+       /* submit buffer */
+       batch->start = buffers[num_buffers-1]->offset;
+       DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
+                 batch->start, batch->used, batch->num_cliprects);
+       ret = i915_dispatch_batchbuffer(dev, batch);
+       if (ret)
+               goto out_err0;
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       /* fence */
+       ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence);
+       if (ret)
+               goto out_err0;
+       if (!(fence_arg->flags & DRM_FENCE_FLAG_NO_USER)) {
+               ret = drm_fence_add_user_object(file_priv, fence, fence_arg->flags & DRM_FENCE_FLAG_SHAREABLE);
+               if (!ret) {
+                       fence_arg->handle = fence->base.hash.key;
+                       fence_arg->fence_class = fence->fence_class;
+                       fence_arg->type = fence->type;
+                       fence_arg->signaled = fence->signaled;
+               }
+       }
+       drm_fence_usage_deref_unlocked(&fence);
+ out_err0:
+       /* handle errors */
+       mutex_lock(&dev->struct_mutex);
+       i915_dereference_buffers_locked(buffers, num_buffers);
+       mutex_unlock(&dev->struct_mutex);
+ out_free:
+       drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER);
+       return ret;
+ }
+ #endif
 +int i915_do_cleanup_pageflip(struct drm_device * dev)
  {
 -      drm_i915_private_t *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
        int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
  
        DRM_DEBUG("%s\n", __FUNCTION__);
@@@ -319,4 -326,40 +326,40 @@@ typedef struct drm_i915_hws_addr 
        uint64_t addr;
  } drm_i915_hws_addr_t;
  
 -      struct _drm_i915_batchbuffer batch;
+ /*
+  * Relocation header is 4 uint32_ts
+  * 0 - (16-bit relocation type << 16)| 16 bit reloc count
+  * 1 - buffer handle for another list of relocs
+  * 2-3 - spare.
+  */
+ #define I915_RELOC_HEADER 4
+ /*
+  * type 0 relocation has 4-uint32_t stride
+  * 0 - offset into buffer
+  * 1 - delta to add in
+  * 2 - index into buffer list
+  * 3 - reserved (for optimisations later).
+  */
+ #define I915_RELOC_TYPE_0 0
+ #define I915_RELOC0_STRIDE 4
+ struct drm_i915_op_arg {
+       uint64_t next;
+       uint32_t reloc_handle;
+       int handled;
+       union {
+               struct drm_bo_op_req req;
+               struct drm_bo_arg_rep rep;
+       } d;
+ };
+ struct drm_i915_execbuffer {
+       uint64_t ops_list;
+       uint32_t num_buffers;
++      struct drm_i915_batchbuffer batch;
+       struct drm_fence_arg fence_arg;
+ };
  #endif                                /* _I915_DRM_H_ */
  #endif
  #define DRIVER_PATCHLEVEL     0
  
 -typedef struct _drm_i915_ring_buffer {
+ #ifdef I915_HAVE_BUFFER
+ #define I915_MAX_VALIDATE_BUFFERS 4096
+ #endif
 +struct drm_i915_ring_buffer {
        int tail_mask;
        unsigned long Start;
        unsigned long End;
@@@ -137,72 -138,14 +142,74 @@@ struct drm_i915_private 
  #endif
  #ifdef I915_HAVE_BUFFER
        void *agp_iomap;
+       unsigned int max_validate_buffers;
  #endif
        DRM_SPINTYPE swaps_lock;
 -      drm_i915_vbl_swap_t vbl_swaps;
 +      struct drm_i915_vbl_swap vbl_swaps;
        unsigned int swaps_pending;
  
 -} drm_i915_private_t;
 +      /* LVDS info */
 +      int backlight_duty_cycle;  /* restore backlight to this value */
 +      bool panel_wants_dither;
 +      struct drm_display_mode *panel_fixed_mode;
 +
 +      /* Register state */
 +      u32 saveDSPACNTR;
 +      u32 saveDSPBCNTR;
 +      u32 savePIPEACONF;
 +      u32 savePIPEBCONF;
 +      u32 savePIPEASRC;
 +      u32 savePIPEBSRC;
 +      u32 saveFPA0;
 +      u32 saveFPA1;
 +      u32 saveDPLL_A;
 +      u32 saveDPLL_A_MD;
 +      u32 saveHTOTAL_A;
 +      u32 saveHBLANK_A;
 +      u32 saveHSYNC_A;
 +      u32 saveVTOTAL_A;
 +      u32 saveVBLANK_A;
 +      u32 saveVSYNC_A;
 +      u32 saveDSPASTRIDE;
 +      u32 saveDSPASIZE;
 +      u32 saveDSPAPOS;
 +      u32 saveDSPABASE;
 +      u32 saveDSPASURF;
 +      u32 saveFPB0;
 +      u32 saveFPB1;
 +      u32 saveDPLL_B;
 +      u32 saveDPLL_B_MD;
 +      u32 saveHTOTAL_B;
 +      u32 saveHBLANK_B;
 +      u32 saveHSYNC_B;
 +      u32 saveVTOTAL_B;
 +      u32 saveVBLANK_B;
 +      u32 saveVSYNC_B;
 +      u32 saveDSPBSTRIDE;
 +      u32 saveDSPBSIZE;
 +      u32 saveDSPBPOS;
 +      u32 saveDSPBBASE;
 +      u32 saveDSPBSURF;
 +      u32 saveVCLK_DIVISOR_VGA0;
 +      u32 saveVCLK_DIVISOR_VGA1;
 +      u32 saveVCLK_POST_DIV;
 +      u32 saveVGACNTRL;
 +      u32 saveADPA;
 +      u32 saveLVDS;
 +      u32 saveDVOA;
 +      u32 saveDVOB;
 +      u32 saveDVOC;
 +      u32 savePP_ON;
 +      u32 savePP_OFF;
 +      u32 savePP_CONTROL;
 +      u32 savePP_CYCLE;
 +      u32 savePFIT_CONTROL;
 +      u32 savePaletteA[256];
 +      u32 savePaletteB[256];
 +      u32 saveSWF[17];
 +      u32 saveBLC_PWM_CTL;
 +};
  
  enum intel_chip_family {
        CHIP_I8XX = 0x01,
Simple merge