diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/Makefile.kernel | 5 | ||||
| -rw-r--r-- | linux-core/drmP.h | 20 | ||||
| -rw-r--r-- | linux-core/drm_agpsupport.c | 16 | ||||
| -rw-r--r-- | linux-core/drm_bo.c | 18 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 4 | ||||
| -rw-r--r-- | linux-core/drm_objects.h | 1 | ||||
| -rw-r--r-- | linux-core/drm_stub.c | 7 | ||||
| -rw-r--r-- | linux-core/drm_sysfs.c | 151 | ||||
| -rw-r--r-- | linux-core/drm_ttm.c | 7 | ||||
| -rw-r--r-- | linux-core/i915_buffer.c | 33 | ||||
| -rw-r--r-- | linux-core/i915_compat.c | 140 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 511 | ||||
| -rw-r--r-- | linux-core/nouveau_buffer.c | 145 | ||||
| -rw-r--r-- | linux-core/nouveau_drv.c | 22 | 
14 files changed, 862 insertions, 218 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 0ed5471a..fd6f5772 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -21,10 +21,11 @@ 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 intel_display.o intel_crt.o intel_lvds.o \ -		intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o +		intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o \ +		i915_compat.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_swmthd.o \ -		nouveau_sgdma.o nouveau_dma.o \ +		nouveau_sgdma.o nouveau_dma.o nouveau_buffer.o \  		nv04_timer.o \  		nv04_mc.o nv40_mc.o nv50_mc.o \  		nv04_fb.o nv10_fb.o nv40_fb.o \ diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 2d1f6db8..8124bd78 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -590,6 +590,15 @@ struct drm_vbl_sig {  	struct task_struct *task;  }; +/** + * Drawable information. + */ +struct drm_drawable_info { +	unsigned int num_rects; +	struct drm_clip_rect *rects; +}; + +  /* location of GART table */  #define DRM_ATI_GART_MAIN 1  #define DRM_ATI_GART_FB   2 @@ -623,6 +632,8 @@ struct drm_driver {  	void (*postclose) (struct drm_device *, struct drm_file *);  	void (*lastclose) (struct drm_device *);  	int (*unload) (struct drm_device *); +	int (*suspend) (struct drm_device *); +	int (*resume) (struct drm_device *);  	int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);  	void (*dma_ready) (struct drm_device *);  	int (*dma_quiescent) (struct drm_device *); @@ -705,6 +716,7 @@ struct drm_head {   * may contain multiple heads.   */  struct drm_device { +	struct device dev;		/**< Linux device */  	char *unique;			/**< Unique identifier: e.g., busid */  	int unique_len;			/**< Length of unique field */  	char *devname;			/**< For /proc/interrupts */ @@ -1143,6 +1155,7 @@ extern int drm_agp_free_memory(DRM_AGP_MEM * handle);  extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);  extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);  extern struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev); +extern void drm_agp_chipset_flush(struct drm_device *dev);  				/* Stub support (drm_stub.h) */  extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,  		     struct drm_driver *driver); @@ -1186,10 +1199,9 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);  			       /* sysfs support (drm_sysfs.c) */  struct drm_sysfs_class;  extern struct class *drm_sysfs_create(struct module *owner, char *name); -extern void drm_sysfs_destroy(struct class *cs); -extern struct class_device *drm_sysfs_device_add(struct class *cs, -						 struct drm_head * head); -extern void drm_sysfs_device_remove(struct class_device *class_dev); +extern void drm_sysfs_destroy(void); +extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head * head); +extern void drm_sysfs_device_remove(struct drm_device *dev);  /*   * Basic memory manager support (drm_mm.c) diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index b68efc64..7c50f411 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -541,11 +541,15 @@ static int drm_agp_bind_ttm(struct drm_ttm_backend *backend,  		container_of(backend, struct drm_agp_ttm_backend, backend);  	DRM_AGP_MEM *mem = agp_be->mem;  	int ret; +	int snooped = (bo_mem->flags & DRM_BO_FLAG_CACHED) && !(bo_mem->flags & DRM_BO_FLAG_CACHED_MAPPED);  	DRM_DEBUG("drm_agp_bind_ttm\n");  	mem->is_flushed = TRUE; -	mem->type = (bo_mem->flags & DRM_BO_FLAG_CACHED) ? AGP_USER_CACHED_MEMORY : -		AGP_USER_MEMORY; +	mem->type = AGP_USER_MEMORY; +	/* CACHED MAPPED implies not snooped memory */ +	if (snooped) +		mem->type = AGP_USER_CACHED_MEMORY; +  	ret = drm_agp_bind_memory(mem, bo_mem->mm_node->start);  	if (ret) {  		DRM_ERROR("AGP Bind memory failed\n"); @@ -650,4 +654,12 @@ struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev)  }  EXPORT_SYMBOL(drm_agp_init_ttm); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +void drm_agp_flush_chipset(struct drm_device *dev) +{ +	agp_flush_chipset(dev->agp->bridge); +} +EXPORT_SYMBOL(drm_agp_flush_chipset); +#endif +  #endif				/* __OS_HAS_AGP */ diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 04900fec..f7f0a197 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -805,6 +805,9 @@ static int drm_bo_mt_compatible(struct drm_mem_type_manager * man,  	}  	flag_diff = (mask ^ cur_flags); +	if (flag_diff & DRM_BO_FLAG_CACHED_MAPPED) +		cur_flags |= DRM_BO_FLAG_CACHED_MAPPED; +  	if ((flag_diff & DRM_BO_FLAG_CACHED) &&  	    (!(mask & DRM_BO_FLAG_CACHED) ||  	     (mask & DRM_BO_FLAG_FORCE_CACHING))) @@ -1028,7 +1031,7 @@ static int drm_bo_busy(struct drm_buffer_object * bo)  	return 0;  } -static int drm_bo_read_cached(struct drm_buffer_object * bo) +static int drm_bo_evict_cached(struct drm_buffer_object * bo)  {  	int ret = 0; @@ -1176,15 +1179,11 @@ static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle,  				goto out;  			} -			if ((map_flags & DRM_BO_FLAG_READ) && -			    (bo->mem.flags & DRM_BO_FLAG_READ_CACHED) && -			    (!(bo->mem.flags & DRM_BO_FLAG_CACHED))) { -				drm_bo_read_cached(bo); -			} +			if (bo->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) +				drm_bo_evict_cached(bo); +  			break; -		} else if ((map_flags & DRM_BO_FLAG_READ) && -			   (bo->mem.flags & DRM_BO_FLAG_READ_CACHED) && -			   (!(bo->mem.flags & DRM_BO_FLAG_CACHED))) { +		} else if (bo->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) {  			/*  			 * We are already mapped with different flags. @@ -1665,7 +1664,6 @@ int drm_buffer_object_create(struct drm_device *dev,  		DRM_BO_FLAG_MAPPABLE;  	atomic_inc(&bm->count);  	ret = drm_bo_new_mask(bo, mask, hint); -  	if (ret)  		goto out_err; diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 4a871d63..1c9895eb 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -534,7 +534,7 @@ static int __init drm_core_init(void)  		 CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);  	return 0;  err_p3: -	drm_sysfs_destroy(drm_class); +	drm_sysfs_destroy();  err_p2:  	unregister_chrdev(DRM_MAJOR, "drm");  	drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB); @@ -545,7 +545,7 @@ err_p1:  static void __exit drm_core_exit(void)  {  	remove_proc_entry("dri", NULL); -	drm_sysfs_destroy(drm_class); +	drm_sysfs_destroy();  	unregister_chrdev(DRM_MAJOR, "drm"); diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index ed9a87ae..6d1d0b9f 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -464,6 +464,7 @@ struct drm_bo_driver {  	 uint32_t(*evict_mask) (struct drm_buffer_object *bo);  	int (*move) (struct drm_buffer_object * bo,  		     int evict, int no_wait, struct drm_bo_mem_reg * new_mem); +	void (*ttm_cache_flush)(struct drm_ttm *ttm);  };  /* diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 34e8d2b8..d947ed63 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -183,11 +183,10 @@ static int drm_get_head(struct drm_device * dev, struct drm_head * head)  				goto err_g1;  			} -			head->dev_class = drm_sysfs_device_add(drm_class, head); -			if (IS_ERR(head->dev_class)) { +			ret = drm_sysfs_device_add(dev, head); +			if (ret) {  				printk(KERN_ERR  				       "DRM: Error sysfs_device_add.\n"); -				ret = PTR_ERR(head->dev_class);  				goto err_g2;  			}  			*heads = head; @@ -316,7 +315,7 @@ int drm_put_head(struct drm_head * head)  	DRM_DEBUG("release secondary minor %d\n", minor);  	drm_proc_cleanup(minor, drm_proc_root, head->dev_root); -	drm_sysfs_device_remove(head->dev_class); +	drm_sysfs_device_remove(head->dev);  	*head = (struct drm_head){.dev = NULL}; diff --git a/linux-core/drm_sysfs.c b/linux-core/drm_sysfs.c index cf4349b0..6f8623ce 100644 --- a/linux-core/drm_sysfs.c +++ b/linux-core/drm_sysfs.c @@ -19,6 +19,45 @@  #include "drm_core.h"  #include "drmP.h" +#define to_drm_device(d) container_of(d, struct drm_device, dev) + +/** + * drm_sysfs_suspend - DRM class suspend hook + * @dev: Linux device to suspend + * @state: power state to enter + * + * Just figures out what the actual struct drm_device associated with + * @dev is and calls its suspend hook, if present. + */ +static int drm_sysfs_suspend(struct device *dev, pm_message_t state) +{ +	struct drm_device *drm_dev = to_drm_device(dev); + +	printk(KERN_ERR "%s\n", __FUNCTION__); + +	if (drm_dev->driver->suspend) +		return drm_dev->driver->suspend(drm_dev); + +	return 0; +} + +/** + * drm_sysfs_resume - DRM class resume hook + * @dev: Linux device to resume + * + * Just figures out what the actual struct drm_device associated with + * @dev is and calls its resume hook, if present. + */ +static int drm_sysfs_resume(struct device *dev) +{ +	struct drm_device *drm_dev = to_drm_device(dev); + +	if (drm_dev->driver->resume) +		return drm_dev->driver->resume(drm_dev); + +	return 0; +} +  /* Display the version of drm_core. This doesn't work right in current design */  static ssize_t version_show(struct class *dev, char *buf)  { @@ -33,7 +72,7 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);   * @owner: pointer to the module that is to "own" this struct drm_sysfs_class   * @name: pointer to a string for the name of this class.   * - * This is used to create a struct drm_sysfs_class pointer that can then be used + * This is used to create DRM class pointer that can then be used   * in calls to drm_sysfs_device_add().   *   * Note, the pointer created here is to be destroyed when finished by making a @@ -50,6 +89,9 @@ struct class *drm_sysfs_create(struct module *owner, char *name)  		goto err_out;  	} +	class->suspend = drm_sysfs_suspend; +	class->resume = drm_sysfs_resume; +  	err = class_create_file(class, &class_attr_version);  	if (err)  		goto err_out_class; @@ -63,94 +105,105 @@ err_out:  }  /** - * drm_sysfs_destroy - destroys a struct drm_sysfs_class structure - * @cs: pointer to the struct drm_sysfs_class that is to be destroyed + * drm_sysfs_destroy - destroys DRM class   * - * Note, the pointer to be destroyed must have been created with a call to - * drm_sysfs_create(). + * Destroy the DRM device class.   */ -void drm_sysfs_destroy(struct class *class) +void drm_sysfs_destroy(void)  { -	if ((class == NULL) || (IS_ERR(class))) +	if ((drm_class == NULL) || (IS_ERR(drm_class)))  		return; - -	class_remove_file(class, &class_attr_version); -	class_destroy(class); +	class_remove_file(drm_class, &class_attr_version); +	class_destroy(drm_class);  } -static ssize_t show_dri(struct class_device *class_device, char *buf) +static ssize_t show_dri(struct device *device, struct device_attribute *attr, +			char *buf)  { -	struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev; +	struct drm_device *dev = to_drm_device(device);  	if (dev->driver->dri_library_name)  		return dev->driver->dri_library_name(dev, buf);  	return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);  } -static struct class_device_attribute class_device_attrs[] = { +static struct device_attribute device_attrs[] = {  	__ATTR(dri_library_name, S_IRUGO, show_dri, NULL),  };  /** + * drm_sysfs_device_release - do nothing + * @dev: Linux device + * + * Normally, this would free the DRM device associated with @dev, along + * with cleaning up any other stuff.  But we do that in the DRM core, so + * this function can just return and hope that the core does its job. + */ +static void drm_sysfs_device_release(struct device *dev) +{ +	return; +} + +/**   * drm_sysfs_device_add - adds a class device to sysfs for a character driver - * @cs: pointer to the struct class that this device should be registered to. - * @dev: the dev_t for the device to be added. - * @device: a pointer to a struct device that is assiociated with this class device. - * @fmt: string for the class device's name + * @dev: DRM device to be added + * @head: DRM head in question   * - * A struct class_device will be created in sysfs, registered to the specified - * class.  A "dev" file will be created, showing the dev_t for the device.  The - * pointer to the struct class_device will be returned from the call.  Any further - * sysfs files that might be required can be created using this pointer. - * Note: the struct class passed to this function must have previously been - * created with a call to drm_sysfs_create(). + * Add a DRM device to the DRM's device model class.  We use @dev's PCI device + * as the parent for the Linux device, and make sure it has a file containing + * the driver we're using (for userspace compatibility).   */ -struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head) +int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)  { -	struct class_device *class_dev; -	int i, j, err; - -	class_dev = class_device_create(cs, NULL, -					MKDEV(DRM_MAJOR, head->minor), -					&(head->dev->pdev)->dev, -					"card%d", head->minor); -	if (IS_ERR(class_dev)) { -		err = PTR_ERR(class_dev); +	int err; +	int i, j; + +	dev->dev.parent = &dev->pdev->dev; +	dev->dev.class = drm_class; +	dev->dev.release = drm_sysfs_device_release; +	/* +	 * This will actually add the major:minor file so that udev +	 * will create the device node.  We don't want to do that just +	 * yet... +	 */ +	/* dev->dev.devt = head->device; */ +	snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor); + +	err = device_register(&dev->dev); +	if (err) { +		DRM_ERROR("device add failed: %d\n", err);  		goto err_out;  	} -	class_set_devdata(class_dev, head); - -	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { -		err = class_device_create_file(class_dev, -					       &class_device_attrs[i]); +	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { +		err = device_create_file(&dev->dev, &device_attrs[i]);  		if (err)  			goto err_out_files;  	} -	return class_dev; +	return 0;  err_out_files:  	if (i > 0)  		for (j = 0; j < i; j++) -			class_device_remove_file(class_dev, -						 &class_device_attrs[i]); -	class_device_unregister(class_dev); +			device_remove_file(&dev->dev, &device_attrs[i]); +	device_unregister(&dev->dev);  err_out: -	return ERR_PTR(err); + +	return err;  }  /** - * drm_sysfs_device_remove - removes a class device that was created with drm_sysfs_device_add() - * @dev: the dev_t of the device that was previously registered. + * drm_sysfs_device_remove - remove DRM device + * @dev: DRM device to remove   *   * This call unregisters and cleans up a class device that was created with a   * call to drm_sysfs_device_add()   */ -void drm_sysfs_device_remove(struct class_device *class_dev) +void drm_sysfs_device_remove(struct drm_device *dev)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) -		class_device_remove_file(class_dev, &class_device_attrs[i]); -	class_device_unregister(class_dev); +	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) +		device_remove_file(&dev->dev, &device_attrs[i]); +	device_unregister(&dev->dev);  } diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 33bbe1d4..fd03f6e8 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -207,6 +207,7 @@ struct page *drm_ttm_get_page(struct drm_ttm * ttm, int index)  	}  	return p;  } +EXPORT_SYMBOL(drm_ttm_get_page);  int drm_ttm_populate(struct drm_ttm * ttm)  { @@ -311,7 +312,7 @@ void drm_ttm_unbind(struct drm_ttm * ttm)  int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem)  { - +	struct drm_bo_driver *bo_driver = ttm->dev->driver->bo_driver;  	int ret = 0;  	struct drm_ttm_backend *be; @@ -328,7 +329,9 @@ int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem)  	if (ttm->state == ttm_unbound && !(bo_mem->flags & DRM_BO_FLAG_CACHED)) {  		drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED); -	} +	} else if ((bo_mem->flags & DRM_BO_FLAG_CACHED_MAPPED) && +		   bo_driver->ttm_cache_flush) +		bo_driver->ttm_cache_flush(ttm);  	if ((ret = be->func->bind(be, bo_mem))) {  		ttm->state = ttm_evicted; diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 01fae64a..e73b4383 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -252,3 +252,36 @@ int i915_move(struct drm_buffer_object * bo,  	}  	return 0;  } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +static inline void clflush(volatile void *__p) +{ +	asm volatile("clflush %0" : "+m" (*(char __force *)__p)); +} +#endif + +static inline void drm_cache_flush_addr(void *virt) +{  +        int i; + +	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) +		clflush(virt+i); +} + +static inline void drm_cache_flush_page(struct page *p) +{ +	drm_cache_flush_addr(page_address(p)); +} + +void i915_flush_ttm(struct drm_ttm *ttm) +{ +	int i; + +	if (!ttm) +		return; + +	DRM_MEMORYBARRIER(); +	for (i = ttm->num_pages-1; i >= 0; i--) +		drm_cache_flush_page(drm_ttm_get_page(ttm, i)); +	DRM_MEMORYBARRIER(); +} diff --git a/linux-core/i915_compat.c b/linux-core/i915_compat.c new file mode 100644 index 00000000..969d5977 --- /dev/null +++ b/linux-core/i915_compat.c @@ -0,0 +1,140 @@ +#include "drmP.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +#define PCI_DEVICE_ID_INTEL_82946GZ_HB      0x2970 +#define PCI_DEVICE_ID_INTEL_82965G_1_HB     0x2980 +#define PCI_DEVICE_ID_INTEL_82965Q_HB       0x2990 +#define PCI_DEVICE_ID_INTEL_82965G_HB       0x29A0 +#define PCI_DEVICE_ID_INTEL_82965GM_HB      0x2A00 +#define PCI_DEVICE_ID_INTEL_82965GME_HB     0x2A10 +#define PCI_DEVICE_ID_INTEL_82945GME_HB     0x27AC +#define PCI_DEVICE_ID_INTEL_G33_HB          0x29C0 +#define PCI_DEVICE_ID_INTEL_Q35_HB          0x29B0 +#define PCI_DEVICE_ID_INTEL_Q33_HB          0x29D0 + +#define IS_I965 (agp_dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ +                 agp_dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ +                 agp_dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ +                 agp_dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ +                 agp_dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ +                 agp_dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) + +#define IS_G33 (agp_dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ +		agp_dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ +		agp_dev->device == PCI_DEVICE_ID_INTEL_Q33_HB) + +#define I915_IFPADDR    0x60 +#define I965_IFPADDR    0x70 + +static struct _intel_private_compat { +	void __iomem *flush_page; +	struct resource ifp_resource; +} intel_private; + +static void +intel_compat_align_resource(void *data, struct resource *res, +                        resource_size_t size, resource_size_t align) +{ +	return; +} + + +static int intel_alloc_chipset_flush_resource(struct pci_dev *pdev) +{ +	int ret; +	ret = pci_bus_alloc_resource(pdev->bus, &intel_private.ifp_resource, PAGE_SIZE, +				     PAGE_SIZE, PCIBIOS_MIN_MEM, 0, +				     intel_compat_align_resource, pdev); +	if (ret != 0) +		return ret; + +	return 0; +} + +static void intel_i915_setup_chipset_flush(struct pci_dev *pdev) +{ +	int ret; +	u32 temp; + +	pci_read_config_dword(pdev, I915_IFPADDR, &temp); +	if (!(temp & 0x1)) { +		intel_alloc_chipset_flush_resource(pdev); + +		pci_write_config_dword(pdev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); +	} else { +		temp &= ~1; + +		intel_private.ifp_resource.start = temp; +		intel_private.ifp_resource.end = temp + PAGE_SIZE; +		ret = request_resource(&iomem_resource, &intel_private.ifp_resource); +		if (ret) { +			intel_private.ifp_resource.start = 0; +			printk("Failed inserting resource into tree\n"); +		} +	} +} + +static void intel_i965_g33_setup_chipset_flush(struct pci_dev *pdev) +{ +	u32 temp_hi, temp_lo; +	int ret; + +	pci_read_config_dword(pdev, I965_IFPADDR + 4, &temp_hi); +	pci_read_config_dword(pdev, I965_IFPADDR, &temp_lo); + +	if (!(temp_lo & 0x1)) { + +		intel_alloc_chipset_flush_resource(pdev); + +		pci_write_config_dword(pdev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32)); +		pci_write_config_dword(pdev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); +	} else { +		u64 l64; +		 +		temp_lo &= ~0x1; +		l64 = ((u64)temp_hi << 32) | temp_lo; + +		intel_private.ifp_resource.start = l64; +		intel_private.ifp_resource.end = l64 + PAGE_SIZE; +		ret = request_resource(&iomem_resource, &intel_private.ifp_resource); +		if (!ret) { +			intel_private.ifp_resource.start = 0; +			printk("Failed inserting resource into tree\n"); +		} +	} +} + +void intel_init_chipset_flush_compat(struct drm_device *dev) +{ +	struct pci_dev *agp_dev = dev->agp->agp_info.device; + +	intel_private.ifp_resource.name = "GMCH IFPBAR"; +	intel_private.ifp_resource.flags = IORESOURCE_MEM; + +	/* Setup chipset flush for 915 */ +	if (IS_I965 || IS_G33) { +		intel_i965_g33_setup_chipset_flush(agp_dev); +	} else { +		intel_i915_setup_chipset_flush(agp_dev); +	} + +	if (intel_private.ifp_resource.start) { +		intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); +		if (!intel_private.flush_page) +			printk("unable to ioremap flush  page - no chipset flushing"); +	} +} + +void intel_fini_chipset_flush_compat(struct drm_device *dev) +{ +	iounmap(intel_private.flush_page); +	release_resource(&intel_private.ifp_resource); +} + +void drm_agp_chipset_flush(struct drm_device *dev) +{ +	if (intel_private.flush_page) +		writel(1, intel_private.flush_page); +} +#endif diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 27e95d65..2f5e32b1 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -67,20 +67,223 @@ static struct drm_bo_driver i915_bo_driver = {  	.init_mem_type = i915_init_mem_type,  	.evict_mask = i915_evict_mask,  	.move = i915_move, +	.ttm_cache_flush = i915_flush_ttm,  };  #endif -static int i915_suspend(struct pci_dev *pdev, pm_message_t state) +enum pipe { +    PIPE_A = 0, +    PIPE_B, +}; + +static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	if (pipe == PIPE_A) +		return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE); +	else +		return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE); +} + +static void i915_save_palette(struct drm_device *dev, enum pipe pipe)  { -	struct drm_device *dev = pci_get_drvdata(pdev);  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_output *output; +	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); +	u32 *array;  	int i; -	pci_save_state(pdev); +	if (!i915_pipe_enabled(dev, pipe)) +		return; -	/* Save video mode information for native mode-setting. */ -	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR); +	if (pipe == PIPE_A) +		array = dev_priv->save_palette_a; +	else +		array = dev_priv->save_palette_b; + +	for(i = 0; i < 256; i++) +		array[i] = I915_READ(reg + (i << 2)); +} + +static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); +	u32 *array; +	int i; + +	if (!i915_pipe_enabled(dev, pipe)) +		return; + +	if (pipe == PIPE_A) +		array = dev_priv->save_palette_a; +	else +		array = dev_priv->save_palette_b; + +	for(i = 0; i < 256; i++) +		I915_WRITE(reg + (i << 2), array[i]); +} + +static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg) +{ +	outb(reg, index_port); +	return inb(data_port); +} + +static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable) +{ +	inb(st01); +	outb(palette_enable | reg, VGA_AR_INDEX); +	return inb(VGA_AR_DATA_READ); +} + +static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable) +{ +	inb(st01); +	outb(palette_enable | reg, VGA_AR_INDEX); +	outb(val, VGA_AR_DATA_WRITE); +} + +static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val) +{ +	outb(reg, index_port); +	outb(val, data_port); +} + +static void i915_save_vga(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int i; +	u16 cr_index, cr_data, st01; + +	/* VGA color palette registers */ +	dev_priv->saveDACMASK = inb(VGA_DACMASK); +	/* DACCRX automatically increments during read */ +	outb(0, VGA_DACRX); +	/* Read 3 bytes of color data from each index */ +	for (i = 0; i < 256 * 3; i++) +		dev_priv->saveDACDATA[i] = inb(VGA_DACDATA); + +	/* MSR bits */ +	dev_priv->saveMSR = inb(VGA_MSR_READ); +	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) { +		cr_index = VGA_CR_INDEX_CGA; +		cr_data = VGA_CR_DATA_CGA; +		st01 = VGA_ST01_CGA; +	} else { +		cr_index = VGA_CR_INDEX_MDA; +		cr_data = VGA_CR_DATA_MDA; +		st01 = VGA_ST01_MDA; +	} + +	/* CRT controller regs */ +	i915_write_indexed(cr_index, cr_data, 0x11, +			   i915_read_indexed(cr_index, cr_data, 0x11) & +			   (~0x80)); +	for (i = 0; i < 0x24; i++) +		dev_priv->saveCR[i] = +			i915_read_indexed(cr_index, cr_data, i); +	/* Make sure we don't turn off CR group 0 writes */ +	dev_priv->saveCR[0x11] &= ~0x80; + +	/* Attribute controller registers */ +	inb(st01); +	dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX); +	for (i = 0; i < 20; i++) +		dev_priv->saveAR[i] = i915_read_ar(st01, i, 0); +	inb(st01); +	outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX); + +	/* Graphics controller registers */ +	for (i = 0; i < 9; i++) +		dev_priv->saveGR[i] = +			i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i); + +	dev_priv->saveGR[0x10] = +		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10); +	dev_priv->saveGR[0x11] = +		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11); +	dev_priv->saveGR[0x18] = +		i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18); + +	/* Sequencer registers */ +	for (i = 0; i < 8; i++) +		dev_priv->saveSR[i] = +			i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i); +} + +static void i915_restore_vga(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int i; +	u16 cr_index, cr_data, st01; + +	/* MSR bits */ +	outb(dev_priv->saveMSR, VGA_MSR_WRITE); +	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) { +		cr_index = VGA_CR_INDEX_CGA; +		cr_data = VGA_CR_DATA_CGA; +		st01 = VGA_ST01_CGA; +	} else { +		cr_index = VGA_CR_INDEX_MDA; +		cr_data = VGA_CR_DATA_MDA; +		st01 = VGA_ST01_MDA; +	} + +	/* Sequencer registers, don't write SR07 */ +	for (i = 0; i < 7; i++) +		i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i, +				   dev_priv->saveSR[i]); + +	/* CRT controller regs */ +	/* Enable CR group 0 writes */ +	i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]); +	for (i = 0; i < 0x24; i++) +		i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]); + +	/* Graphics controller regs */ +	for (i = 0; i < 9; i++) +		i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i, +				   dev_priv->saveGR[i]); + +	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10, +			   dev_priv->saveGR[0x10]); +	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11, +			   dev_priv->saveGR[0x11]); +	i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18, +			   dev_priv->saveGR[0x18]); + +	/* Attribute controller registers */ +	for (i = 0; i < 20; i++) +		i915_write_ar(st01, i, dev_priv->saveAR[i], 0); +	inb(st01); /* switch back to index mode */ +	outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX); + +	/* VGA color palette registers */ +	outb(dev_priv->saveDACMASK, VGA_DACMASK); +	/* DACCRX automatically increments during read */ +	outb(0, VGA_DACWX); +	/* Read 3 bytes of color data from each index */ +	for (i = 0; i < 256 * 3; i++) +		outb(dev_priv->saveDACDATA[i], VGA_DACDATA); + +} + +static int i915_suspend(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int i; + +	if (!dev || !dev_priv) { +		printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv); +		printk(KERN_ERR "DRM not initialized, aborting suspend.\n"); +		return -ENODEV; +	} + +	pci_save_state(dev->pdev); +	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + +	/* Pipe & plane A info */  	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);  	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);  	dev_priv->saveFPA0 = I915_READ(FPA0); @@ -94,206 +297,228 @@ static int i915_suspend(struct pci_dev *pdev, pm_message_t state)  	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);  	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);  	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); +	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); + +	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);  	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);  	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);  	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);  	dev_priv->saveDSPABASE = I915_READ(DSPABASE); - -	for(i= 0; i < 256; i++) -		dev_priv->savePaletteA[i] = I915_READ(PALETTE_A + (i << 2)); - -	if(dev->mode_config.num_crtc == 2) { -		dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); -		dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); -		dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); -		dev_priv->saveFPB0 = I915_READ(FPB0); -		dev_priv->saveFPB1 = I915_READ(FPB1); -		dev_priv->saveDPLL_B = I915_READ(DPLL_B); -		if (IS_I965G(dev)) -			dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); -		dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); -		dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); -		dev_priv->saveHSYNC_B = I915_READ(HSYNC_B); -		dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); -		dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); -		dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); -		dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); -		dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); -		dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); -		dev_priv->saveDSPBBASE = I915_READ(DSPBBASE); -		for(i= 0; i < 256; i++) -			dev_priv->savePaletteB[i] = -				I915_READ(PALETTE_B + (i << 2)); -	} -  	if (IS_I965G(dev)) {  		dev_priv->saveDSPASURF = I915_READ(DSPASURF); +		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); +	} +	i915_save_palette(dev, PIPE_A); + +	/* Pipe & plane B info */ +	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); +	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); +	dev_priv->saveFPB0 = I915_READ(FPB0); +	dev_priv->saveFPB1 = I915_READ(FPB1); +	dev_priv->saveDPLL_B = I915_READ(DPLL_B); +	if (IS_I965G(dev)) +		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); +	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); +	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); +	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B); +	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); +	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); +	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); +	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); + +	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); +	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); +	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); +	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); +	dev_priv->saveDSPBBASE = I915_READ(DSPBBASE); +	if (IS_I965GM(dev)) {  		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); +		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);  	} +	i915_save_palette(dev, PIPE_B); +	/* CRT state */ +	dev_priv->saveADPA = I915_READ(ADPA); + +	/* LVDS state */ +	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); +	dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); +	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); +	if (IS_I965G(dev)) +		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); +	if (IS_MOBILE(dev) && !IS_I830(dev)) +		dev_priv->saveLVDS = I915_READ(LVDS); +	if (!IS_I830(dev) && !IS_845G(dev)) +		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); +	dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON); +	dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF); +	dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE); + +	/* FIXME: save TV & SDVO state */ + +	/* FBC state */ +	dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); +	dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); +	dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); +	dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); + +	/* VGA state */  	dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);  	dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);  	dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);  	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); -	for(i = 0; i < 7; i++) { -		dev_priv->saveSWF[i] = I915_READ(SWF0 + (i << 2)); -		dev_priv->saveSWF[i+7] = I915_READ(SWF00 + (i << 2)); +	/* Scratch space */ +	for (i = 0; i < 16; i++) { +		dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2)); +		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));  	} -	dev_priv->saveSWF[14] = I915_READ(SWF30); -	dev_priv->saveSWF[15] = I915_READ(SWF31); -	dev_priv->saveSWF[16] = I915_READ(SWF32); +	for (i = 0; i < 3; i++) +		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); -	if (IS_MOBILE(dev) && !IS_I830(dev)) -		dev_priv->saveLVDS = I915_READ(LVDS); -	dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); - -	list_for_each_entry(output, &dev->mode_config.output_list, head) -		if (output->funcs->save) -			(*output->funcs->save) (output); +	i915_save_vga(dev); -#if 0 /* FIXME: save VGA bits */ -	vgaHWUnlock(hwp); -	vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); -#endif -	pci_disable_device(pdev); -	pci_set_power_state(pdev, PCI_D3hot); +	/* Shut down the device */ +	pci_disable_device(dev->pdev); +	pci_set_power_state(dev->pdev, PCI_D3hot);  	return 0;  } -static int i915_resume(struct pci_dev *pdev) +static int i915_resume(struct drm_device *dev)  { -	struct drm_device *dev = pci_get_drvdata(pdev);  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_output *output; -	struct drm_crtc *crtc;  	int i; -	pci_set_power_state(pdev, PCI_D0); -	pci_restore_state(pdev); -	if (pci_enable_device(pdev)) +	pci_set_power_state(dev->pdev, PCI_D0); +	pci_restore_state(dev->pdev); +	if (pci_enable_device(dev->pdev))  		return -1; -	/* Disable outputs */ -	list_for_each_entry(output, &dev->mode_config.output_list, head) -		output->funcs->dpms(output, DPMSModeOff); - -	i915_driver_wait_next_vblank(dev, 0); -    -	/* Disable pipes */ -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -		crtc->funcs->dpms(crtc, DPMSModeOff); - -	/* FIXME: wait for vblank on each pipe? */ -	i915_driver_wait_next_vblank(dev, 0); - -	if (IS_MOBILE(dev) && !IS_I830(dev)) -		I915_WRITE(LVDS, dev_priv->saveLVDS); - -	if (!IS_I830(dev) && !IS_845G(dev)) -		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); +	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); +	/* Pipe & plane A info */ +	/* Prime the clock */  	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { -		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE); +		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & +			   ~DPLL_VCO_ENABLE);  		udelay(150);  	}  	I915_WRITE(FPA0, dev_priv->saveFPA0);  	I915_WRITE(FPA1, dev_priv->saveFPA1); +	/* Actually enable it */  	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);  	udelay(150);  	if (IS_I965G(dev))  		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); -	else -		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);  	udelay(150); +	/* Restore mode */  	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);  	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);  	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);  	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);  	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);  	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); +	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); -	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); +	/* Restore plane info */  	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);  	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);  	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);  	I915_WRITE(DSPABASE, dev_priv->saveDSPABASE); -	if (IS_I965G(dev)) +	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); +	if (IS_I965G(dev)) {  		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); +		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); +	}  	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); -	i915_driver_wait_next_vblank(dev, 0); +	i915_restore_palette(dev, PIPE_A); +	/* Enable the plane */  	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);  	I915_WRITE(DSPABASE, I915_READ(DSPABASE)); -	i915_driver_wait_next_vblank(dev, 0); -    -	if(dev->mode_config.num_crtc == 2) { -		if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { -			I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE); -			udelay(150); -		} -		I915_WRITE(FPB0, dev_priv->saveFPB0); -		I915_WRITE(FPB1, dev_priv->saveFPB1); -		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); -		udelay(150); -		if (IS_I965G(dev)) -			I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); -		else -			I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); + +	/* Pipe & plane B info */ +	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { +		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & +			   ~DPLL_VCO_ENABLE);  		udelay(150); +	} +	I915_WRITE(FPB0, dev_priv->saveFPB0); +	I915_WRITE(FPB1, dev_priv->saveFPB1); +	/* Actually enable it */ +	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); +	udelay(150); +	if (IS_I965G(dev)) +		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); +	udelay(150); -		I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); -		I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); -		I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); -		I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); -		I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); -		I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); -		I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); -		I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); -		I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); -		I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); -		I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE); -		if (IS_I965G(dev)) -			I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); -		I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); -		i915_driver_wait_next_vblank(dev, 0); -		I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); -		I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); -		i915_driver_wait_next_vblank(dev, 0); +	/* Restore mode */ +	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); +	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); +	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); +	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); +	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); +	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); +	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); + +	/* Restore plane info */ +	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); +	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); +	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); +	I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE); +	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); +	if (IS_I965G(dev)) { +		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); +		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);  	} +	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); +	i915_restore_palette(dev, PIPE_A); +	/* Enable the plane */ +	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); +	I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); -	/* Restore outputs */ -	list_for_each_entry(output, &dev->mode_config.output_list, head) -		if (output->funcs->restore) -			output->funcs->restore(output); -     -	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); +	/* CRT state */ +	I915_WRITE(ADPA, dev_priv->saveADPA); +	/* LVDS state */ +	if (IS_I965G(dev)) +		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); +	if (IS_MOBILE(dev) && !IS_I830(dev)) +		I915_WRITE(LVDS, dev_priv->saveLVDS); +	if (!IS_I830(dev) && !IS_845G(dev)) +		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); + +	I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); +	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); +	I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON); +	I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF); +	I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE); +	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + +	/* FIXME: restore TV & SDVO state */ + +	/* FBC info */ +	I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); +	I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); +	I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); +	I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); + +	/* VGA state */ +	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);  	I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);  	I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);  	I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV); +	udelay(150); -	for(i = 0; i < 256; i++) -		I915_WRITE(PALETTE_A + (i << 2), dev_priv->savePaletteA[i]); -    -	if(dev->mode_config.num_crtc == 2) -		for(i= 0; i < 256; i++) -			I915_WRITE(PALETTE_B + (i << 2), dev_priv->savePaletteB[i]); - -	for(i = 0; i < 7; i++) { -		I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF[i]); -		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF[i+7]); +	for (i = 0; i < 16; i++) { +		I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]); +		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);  	} +	for (i = 0; i < 3; i++) +		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); -	I915_WRITE(SWF30, dev_priv->saveSWF[14]); -	I915_WRITE(SWF31, dev_priv->saveSWF[15]); -	I915_WRITE(SWF32, dev_priv->saveSWF[16]); - -#if 0 /* FIXME: restore VGA bits */ -	vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); -	vgaHWLock(hwp); -#endif +	i915_restore_vga(dev);  	return 0;  } @@ -311,6 +536,8 @@ static struct drm_driver driver = {  	.unload = i915_driver_unload,  	.lastclose = i915_driver_lastclose,  	.preclose = i915_driver_preclose, +	.suspend = i915_suspend, +	.resume = i915_resume,  	.device_is_agp = i915_driver_device_is_agp,  	.vblank_wait = i915_driver_vblank_wait,  	.vblank_wait2 = i915_driver_vblank_wait2, @@ -341,8 +568,6 @@ static struct drm_driver driver = {  		.id_table = pciidlist,  		.probe = probe,  		.remove = __devexit_p(drm_cleanup_pci), -		.suspend = i915_suspend, -		.resume = i915_resume,  		},  #ifdef I915_HAVE_FENCE  	.fence_driver = &i915_fence_driver, diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c new file mode 100644 index 00000000..e9f09eb3 --- /dev/null +++ b/linux-core/nouveau_buffer.c @@ -0,0 +1,145 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Authors: Jeremy Kolb <jkolb@brandeis.edu> + */ + +#include "drmP.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" + +#ifdef NOUVEAU_HAVE_BUFFER + +struct drm_ttm_backend *nouveau_create_ttm_backend_entry(struct drm_device * dev) +{ +	struct drm_nouveau_private *dev_priv = dev->dev_private; + +	return drm_agp_init_ttm(dev); +} + +int nouveau_fence_types(struct drm_buffer_object *bo, +			uint32_t *fclass, +			uint32_t *type) +{ +	*fclass = 0; + +	if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) +		*type = 3; +	else +		*type = 1; +	return 0; + +} +int nouveau_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags) +{ +	/* We'll do this from user space. */ +	return 0; +} + +int nouveau_init_mem_type(struct drm_device *dev, +			  uint32_t type, +			  struct drm_mem_type_manager *man) +{ +	struct drm_nouveau_private *dev_priv = dev->dev_private; + +	switch (type) { +		case DRM_BO_MEM_LOCAL: +			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | +				_DRM_FLAG_MEMTYPE_CACHED; +			man->drm_bus_maptype = 0; +			break; + +		case DRM_BO_MEM_VRAM: +			man->flags = _DRM_FLAG_MEMTYPE_FIXED | +				_DRM_FLAG_MEMTYPE_MAPPABLE | +				_DRM_FLAG_NEEDS_IOREMAP; +			man->io_addr = NULL; +			man->drm_bus_maptype = _DRM_FRAME_BUFFER; +			man->io_offset = drm_get_resource_start(dev, 0); +			man->io_size = drm_get_resource_len(dev, 0); +			break; + +		case DRM_BO_MEM_TT: +			if (!(drm_core_has_AGP(dev) && dev->agp)) { +				DRM_ERROR("AGP is not enabled for memory type %u\n", +						(unsigned)type); +				return -EINVAL; +			} + +			man->io_offset = dev->agp->agp_info.aper_base; +			man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; +			man->io_addr = NULL; +			man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | +				_DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; +			man->drm_bus_maptype = _DRM_AGP; +			break; + +		default: +			DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); +			return -EINVAL; +	} +	return 0; +} + +uint32_t nouveau_evict_mask(struct drm_buffer_object *bo) +{ +	switch (bo->mem.mem_type) { +		case DRM_BO_MEM_LOCAL: +		case DRM_BO_MEM_TT: +			return DRM_BO_FLAG_MEM_LOCAL; +		case DRM_BO_MEM_VRAM: +			if (bo->mem.num_pages > 128) +				return DRM_BO_MEM_TT; +			else +				return DRM_BO_MEM_LOCAL; +		default: +			return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; +	} + +} + +int nouveau_move(struct drm_buffer_object *bo, +		 int evict, +		 int no_wait, +		 struct drm_bo_mem_reg *new_mem) +{ +	struct drm_bo_mem_reg *old_mem = &bo->mem; + +	if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { +		return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); +	else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { +		return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); +	} +	else { +		return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); +	} +	return 0; +} + +void nouveau_flush_ttm(struct drm_ttm *ttm) +{ + +} + +#endif diff --git a/linux-core/nouveau_drv.c b/linux-core/nouveau_drv.c index 01de67de..9e6c8f41 100644 --- a/linux-core/nouveau_drv.c +++ b/linux-core/nouveau_drv.c @@ -41,6 +41,25 @@ static struct pci_device_id pciidlist[] = {  	}  }; +#ifdef NOUVEAU_HAVE_BUFFER +static uint32_t nouveau_mem_prios[]  = { DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL }; +static uint32_t nouveau_busy_prios[] = { DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL }; + +static struct drm_bo_driver nouveau_bo_driver = { +	.mem_type_prio = nouveau_mem_prios, +	.mem_busy_prio = nouveau_busy_prios, +	.num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t), +	.num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t), +	.create_ttm_backend_entry = nouveau_create_ttm_backend_entry, +	.fence_type = nouveau_fence_types, +	.invalidate_caches = nouveau_invalidate_caches, +	.init_mem_type = nouveau_init_mem_type, +	.evict_mask = nouveau_evict_mask, +	.move = nouveau_move, +	.ttm_cache_flush= nouveau_flush_ttm +}; +#endif +  extern struct drm_ioctl_desc nouveau_ioctls[];  extern int nouveau_max_ioctl; @@ -80,6 +99,9 @@ static struct drm_driver driver = {  		.probe = probe,  		.remove = __devexit_p(drm_cleanup_pci),  	}, +#ifdef NOUVEAU_HAVE_BUFFER +	.bo_driver = &nouveau_bo_driver, +#endif  	.name = DRIVER_NAME,  	.desc = DRIVER_DESC, | 
