diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/Makefile.kernel | 3 | ||||
| -rw-r--r-- | linux-core/ati_pcigart.c | 49 | ||||
| -rw-r--r-- | linux-core/drmP.h | 15 | ||||
| -rw-r--r-- | linux-core/drm_agpsupport.c | 4 | ||||
| -rw-r--r-- | linux-core/drm_compat.h | 4 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 8 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 136 | ||||
| -rw-r--r-- | linux-core/drm_lock.c | 21 | ||||
| -rw-r--r-- | linux-core/drm_memory.c | 9 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 463 | ||||
| -rw-r--r-- | linux-core/i915_fence.c | 2 | ||||
| -rw-r--r-- | linux-core/i915_gem.c | 22 | ||||
| -rw-r--r-- | linux-core/i915_gem_proc.c | 10 | ||||
| -rw-r--r-- | linux-core/i915_opregion.c | 387 | ||||
| l--------- | linux-core/i915_suspend.c | 1 | ||||
| -rw-r--r-- | linux-core/radeon_drv.c | 24 | ||||
| -rw-r--r-- | linux-core/xgi_cmdlist.c | 8 | ||||
| -rw-r--r-- | linux-core/xgi_drv.c | 25 | ||||
| -rw-r--r-- | linux-core/xgi_drv.h | 21 | ||||
| -rw-r--r-- | linux-core/xgi_fb.c | 4 | ||||
| -rw-r--r-- | linux-core/xgi_fence.c | 92 | ||||
| -rw-r--r-- | linux-core/xgi_misc.c | 26 | 
22 files changed, 728 insertions, 606 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index b114dee5..f338b598 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -20,7 +20,8 @@ r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o  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_compat.o i915_execbuf.o \ +		i915_buffer.o i915_compat.o i915_execbuf.o i915_suspend.o \ +		i915_opregion.o \  		i915_gem.o i915_gem_debug.o i915_gem_proc.o i915_gem_tiling.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 \ diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index 09251ac3..40f8f8dd 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -39,6 +39,28 @@  #define ATI_PCIE_WRITE 0x4  #define ATI_PCIE_READ 0x8 +static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, u32 *pci_gart) +{ +	u32 page_base; + +	page_base = (u32)addr & ATI_PCIGART_PAGE_MASK; +	switch(gart_info->gart_reg_if) { +	case DRM_ATI_GART_IGP: +		page_base |= (upper_32_bits(addr) & 0xff) << 4; +		page_base |= 0xc; +		break; +	case DRM_ATI_GART_PCIE: +		page_base >>= 8; +		page_base |= (upper_32_bits(addr) & 0xff) << 24; +		page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE; +		break; +	default: +	case DRM_ATI_GART_PCI: +		break; +	} +	*pci_gart = cpu_to_le32(page_base); +} +  static int drm_ati_alloc_pcigart_table(struct drm_device *dev,  				       struct drm_ati_pcigart_info *gart_info)  { @@ -80,7 +102,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info  		for (i = 0; i < pages; i++) {  			if (!entry->busaddr[i])  				break; -			pci_unmap_single(dev->pdev, entry->busaddr[i], +			pci_unmap_page(dev->pdev, entry->busaddr[i],  					 PAGE_SIZE, PCI_DMA_TODEVICE);  		} @@ -104,7 +126,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga  	struct drm_sg_mem *entry = dev->sg;  	void *address = NULL;  	unsigned long pages; -	u32 *pci_gart, page_base; +	u32 *pci_gart;  	dma_addr_t bus_address = 0;  	int i, j, ret = 0;  	int max_pages; @@ -143,10 +165,8 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga  	for (i = 0; i < pages; i++) {  		/* we need to support large memory configurations */ -		entry->busaddr[i] = pci_map_single(dev->pdev, -						   page_address(entry-> -								pagelist[i]), -						   PAGE_SIZE, PCI_DMA_TODEVICE); +		entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], +						 0, PAGE_SIZE, PCI_DMA_TODEVICE);  		if (entry->busaddr[i] == 0) {  			DRM_ERROR("unable to map PCIGART pages!\n");  			drm_ati_pcigart_cleanup(dev, gart_info); @@ -157,22 +177,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga  		entry_addr = entry->busaddr[i];  		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { -			page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK; -			switch(gart_info->gart_reg_if) { -			case DRM_ATI_GART_IGP: -				page_base |= (upper_32_bits(entry_addr) & 0xff) << 4; -				page_base |= 0xc; -				break; -			case DRM_ATI_GART_PCIE: -				page_base >>= 8; -				page_base |= (upper_32_bits(entry_addr) & 0xff) << 24; -				page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE; -				break; -			default: -			case DRM_ATI_GART_PCI: -				break; -			} -			*pci_gart = cpu_to_le32(page_base); +			gart_insert_page_into_table(gart_info, entry_addr, pci_gart);  			pci_gart++;  			entry_addr += ATI_PCIGART_PAGE_SIZE;  		} diff --git a/linux-core/drmP.h b/linux-core/drmP.h index ec8a61d4..6b5e1851 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -909,6 +909,14 @@ struct drm_device {  	/** \name VBLANK IRQ support */  	/*@{ */ +	/* +	 * At load time, disabling the vblank interrupt won't be allowed since +	 * old clients may not call the modeset ioctl and therefore misbehave. +	 * Once the modeset ioctl *has* been called though, we can safely +	 * disable them when unused. +	 */ +	int vblank_disable_allowed; +  	wait_queue_head_t *vbl_queue;	/**< VBLANK wait queue */  	atomic_t *_vblank_count;	/**< number of VBLANK interrupts (driver must alloc the right number of counters) */  	spinlock_t vbl_lock; @@ -917,13 +925,12 @@ struct drm_device {  	atomic_t *vblank_refcount;	/* number of users of vblank interrupts per crtc */  	u32 *last_vblank;		/* protected by dev->vbl_lock, used */  					/* for wraparound handling */ -	u32 *vblank_offset;		/* used to track how many vblanks */  	int *vblank_enabled;		/* so we don't call enable more than  					   once per disable */ -	u32 *vblank_premodeset;		/*  were lost during modeset */ +	int *vblank_inmodeset;		/* Display driver is setting mode */  	struct timer_list vblank_disable_timer; -	unsigned long max_vblank_count; /**< size of vblank counter register */ +	u32 max_vblank_count;		/**< size of vblank counter register */  	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */  	void (*locked_tasklet_func)(struct drm_device *dev); @@ -1241,7 +1248,6 @@ extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *  extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);  extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));  extern u32 drm_vblank_count(struct drm_device *dev, int crtc); -extern void drm_update_vblank_count(struct drm_device *dev, int crtc);  extern void drm_handle_vblank(struct drm_device *dev, int crtc);  extern int drm_vblank_get(struct drm_device *dev, int crtc);  extern void drm_vblank_put(struct drm_device *dev, int crtc); @@ -1420,6 +1426,7 @@ void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);  void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);  extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev); +extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);  extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);  static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index d6594b87..6ccb4b6d 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -597,7 +597,7 @@ static int drm_agp_bind_ttm(struct drm_ttm_backend *backend,  	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->is_flushed = true;  	mem->type = AGP_USER_MEMORY;  	/* CACHED MAPPED implies not snooped memory */  	if (snooped) @@ -696,7 +696,7 @@ struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev)  	agp_be->mem = NULL;  	agp_be->bridge = dev->agp->bridge; -	agp_be->populated = FALSE; +	agp_be->populated = false;  	agp_be->backend.func = &agp_ttm_backend;  	agp_be->backend.dev = dev; diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 6aa19c55..6e5d252b 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -362,4 +362,8 @@ extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,  				     unsigned long address, int *type);  #endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) +#define drm_core_ioremap_wc drm_core_ioremap +#endif +  #endif diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index bc32ed50..c2445671 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -617,9 +617,10 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)  		&& (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))  		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; -	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) +	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {  		ioctl = &drm_ioctls[nr]; -	else { +		cmd = ioctl->cmd; +	} else {  		retcode = -EINVAL;  		goto err_i1;  	} @@ -635,6 +636,7 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		goto err_i1;  	}  #endif +  	func = ioctl->func;  	/* is there a local override? */  	if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl) @@ -659,7 +661,7 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		retcode = func(dev, kdata, file_priv);  	} -	if ((retcode == 0) && (cmd & IOC_OUT)) { +	if (cmd & IOC_OUT) {  		if (copy_to_user((void __user *)arg, kdata,  				 _IOC_SIZE(cmd)) != 0)  			retcode = -EACCES; diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 961f90c4..5b9f474b 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -77,10 +77,16 @@ static void vblank_disable_fn(unsigned long arg)  	unsigned long irqflags;  	int i; +	if (!dev->vblank_disable_allowed) +		return; +  	for (i = 0; i < dev->num_crtcs; i++) {  		spin_lock_irqsave(&dev->vbl_lock, irqflags);  		if (atomic_read(&dev->vblank_refcount[i]) == 0 &&  		    dev->vblank_enabled[i]) { +			DRM_DEBUG("disabling vblank on crtc %d\n", i); +			dev->last_vblank[i] = +				dev->driver->get_vblank_counter(dev, i);  			dev->driver->disable_vblank(dev, i);  			dev->vblank_enabled[i] = 0;  		} @@ -110,10 +116,8 @@ static void drm_vblank_cleanup(struct drm_device *dev)  		 dev->num_crtcs, DRM_MEM_DRIVER);  	drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,  		 DRM_MEM_DRIVER); -	drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * +	drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *  		 dev->num_crtcs, DRM_MEM_DRIVER); -	drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs, -		 DRM_MEM_DRIVER);  	dev->num_crtcs = 0;  } @@ -158,13 +162,9 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)  	if (!dev->last_vblank)  		goto err; -	dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32), -					    DRM_MEM_DRIVER); -	if (!dev->vblank_premodeset) -		goto err; - -	dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); -	if (!dev->vblank_offset) +	dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int), +					 DRM_MEM_DRIVER); +	if (!dev->vblank_inmodeset)  		goto err;  	/* Zero per-crtc vblank stuff */ @@ -175,6 +175,8 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)  		atomic_set(&dev->vblank_refcount[i], 0);  	} +	dev->vblank_disable_allowed = 0; +  	return 0;  err: @@ -335,8 +337,7 @@ int drm_control(struct drm_device *dev, void *data,   */  u32 drm_vblank_count(struct drm_device *dev, int crtc)  { -	return atomic_read(&dev->_vblank_count[crtc]) + -		dev->vblank_offset[crtc]; +	return atomic_read(&dev->_vblank_count[crtc]);  }  EXPORT_SYMBOL(drm_vblank_count); @@ -349,10 +350,15 @@ EXPORT_SYMBOL(drm_vblank_count);   * (specified by @crtc).  Deal with wraparound, if it occurred, and   * update the last read value so we can deal with wraparound on the next   * call if necessary. + * + * Only necessary when going from off->on, to account for frames we + * didn't get an interrupt for. + * + * Note: caller must hold dev->vbl_lock since this reads & writes + * device vblank fields.   */ -void drm_update_vblank_count(struct drm_device *dev, int crtc) +static void drm_update_vblank_count(struct drm_device *dev, int crtc)  { -	unsigned long irqflags;  	u32 cur_vblank, diff;  	/* @@ -363,20 +369,19 @@ void drm_update_vblank_count(struct drm_device *dev, int crtc)  	 * a long time.  	 */  	cur_vblank = dev->driver->get_vblank_counter(dev, crtc); -	spin_lock_irqsave(&dev->vbl_lock, irqflags); +	diff = cur_vblank - dev->last_vblank[crtc];  	if (cur_vblank < dev->last_vblank[crtc]) { -		diff = dev->max_vblank_count - -			dev->last_vblank[crtc]; -		diff += cur_vblank; -	} else { -		diff = cur_vblank - dev->last_vblank[crtc]; +		diff += dev->max_vblank_count; + +		DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", +			  crtc, dev->last_vblank[crtc], cur_vblank, diff);  	} -	dev->last_vblank[crtc] = cur_vblank; -	spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + +	DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", +		  crtc, diff);  	atomic_add(diff, &dev->_vblank_count[crtc]);  } -EXPORT_SYMBOL(drm_update_vblank_count);  /**   * drm_vblank_get - get a reference count on vblank events @@ -384,9 +389,7 @@ EXPORT_SYMBOL(drm_update_vblank_count);   * @crtc: which CRTC to own   *   * Acquire a reference count on vblank events to avoid having them disabled - * while in use.  Note callers will probably want to update the master counter - * using drm_update_vblank_count() above before calling this routine so that - * wakeups occur on the right vblank event. + * while in use.   *   * RETURNS   * Zero on success, nonzero on failure. @@ -396,15 +399,17 @@ int drm_vblank_get(struct drm_device *dev, int crtc)  	unsigned long irqflags;  	int ret = 0; -	spin_lock_irqsave(&dev->vbl_lock, irqflags);	 +	spin_lock_irqsave(&dev->vbl_lock, irqflags);  	/* Going from 0->1 means we have to enable interrupts again */  	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&  	    !dev->vblank_enabled[crtc]) {  		ret = dev->driver->enable_vblank(dev, crtc);  		if (ret)  			atomic_dec(&dev->vblank_refcount[crtc]); -		else +		else {  			dev->vblank_enabled[crtc] = 1; +			drm_update_vblank_count(dev, crtc); +		}  	}  	spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -434,13 +439,21 @@ EXPORT_SYMBOL(drm_vblank_put);   *   * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET   * ioctls around modesetting so that any lost vblank events are accounted for. + * + * Generally the counter will reset across mode sets.  If interrupts are + * enabled around this call, we don't have to do anything since the counter + * will have already been incremented.   */  int drm_modeset_ctl(struct drm_device *dev, void *data,  		    struct drm_file *file_priv)  {  	struct drm_modeset_ctl *modeset = data; +	unsigned long irqflags;  	int crtc, ret = 0; -	u32 new; + +	/* If drm_vblank_init() hasn't been called yet, just no-op */ +	if (!dev->num_crtcs) +		goto out;  	crtc = modeset->crtc;  	if (crtc >= dev->num_crtcs) { @@ -448,14 +461,28 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,  		goto out;  	} +	/* +	 * To avoid all the problems that might happen if interrupts +	 * were enabled/disabled around or between these calls, we just +	 * have the kernel take a reference on the CRTC (just once though +	 * to avoid corrupting the count if multiple, mismatch calls occur), +	 * so that interrupts remain enabled in the interim. +	 */  	switch (modeset->cmd) {  	case _DRM_PRE_MODESET: -		dev->vblank_premodeset[crtc] = -			dev->driver->get_vblank_counter(dev, crtc); +		if (!dev->vblank_inmodeset[crtc]) { +			dev->vblank_inmodeset[crtc] = 1; +			drm_vblank_get(dev, crtc); +		}  		break;  	case _DRM_POST_MODESET: -		new = dev->driver->get_vblank_counter(dev, crtc); -		dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new; +		if (dev->vblank_inmodeset[crtc]) { +			spin_lock_irqsave(&dev->vbl_lock, irqflags); +			dev->vblank_disable_allowed = 1; +			dev->vblank_inmodeset[crtc] = 0; +			spin_unlock_irqrestore(&dev->vbl_lock, irqflags); +			drm_vblank_put(dev, crtc); +		}  		break;  	default:  		ret = -EINVAL; @@ -489,7 +516,6 @@ int drm_wait_vblank(struct drm_device *dev, void *data,  		    struct drm_file *file_priv)  {  	union drm_wait_vblank *vblwait = data; -	struct timeval now;  	int ret = 0;  	unsigned int flags, seq, crtc; @@ -510,7 +536,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,  	if (crtc >= dev->num_crtcs)  		return -EINVAL; -	drm_update_vblank_count(dev, crtc); +	ret = drm_vblank_get(dev, crtc); +	if (ret) +		return ret;  	seq = drm_vblank_count(dev, crtc);  	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { @@ -520,7 +548,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,  	case _DRM_VBLANK_ABSOLUTE:  		break;  	default: -		return -EINVAL; +		ret = -EINVAL; +		goto done;  	}  	if ((flags & _DRM_VBLANK_NEXTONMISS) && @@ -553,15 +582,18 @@ int drm_wait_vblank(struct drm_device *dev, void *data,  		if (atomic_read(&dev->vbl_signal_pending) >= 100) {  			spin_unlock_irqrestore(&dev->vbl_lock, irqflags); -			return -EBUSY; +			ret = -EBUSY; +			goto done;  		}  		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);  		vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),  				     DRM_MEM_DRIVER); -		if (!vbl_sig) -			return -ENOMEM; +		if (!vbl_sig) { +			ret = -ENOMEM; +			goto done; +		}  		ret = drm_vblank_get(dev, crtc);  		if (ret) { @@ -584,23 +616,23 @@ int drm_wait_vblank(struct drm_device *dev, void *data,  		vblwait->reply.sequence = seq;  	} else { -		unsigned long cur_vblank; - -		ret = drm_vblank_get(dev, crtc); -		if (ret) -			return ret;  		DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, -			    (((cur_vblank = drm_vblank_count(dev, crtc)) +			    ((drm_vblank_count(dev, crtc)  			      - vblwait->request.sequence) <= (1 << 23))); -		drm_vblank_put(dev, crtc); -		do_gettimeofday(&now); -		vblwait->reply.tval_sec = now.tv_sec; -		vblwait->reply.tval_usec = now.tv_usec; -		vblwait->reply.sequence = cur_vblank; +		if (ret != -EINTR) { +			struct timeval now; + +			do_gettimeofday(&now); + +			vblwait->reply.tval_sec = now.tv_sec; +			vblwait->reply.tval_usec = now.tv_usec; +			vblwait->reply.sequence = drm_vblank_count(dev, crtc); +		}  	} -      done: +done: +	drm_vblank_put(dev, crtc);  	return ret;  } @@ -654,7 +686,7 @@ static void drm_vbl_send_signals(struct drm_device * dev, int crtc)   */  void drm_handle_vblank(struct drm_device *dev, int crtc)  { -	drm_update_vblank_count(dev, crtc); +	atomic_inc(&dev->_vblank_count[crtc]);  	DRM_WAKEUP(&dev->vbl_queue[crtc]);  	drm_vbl_send_signals(dev, crtc);  } diff --git a/linux-core/drm_lock.c b/linux-core/drm_lock.c index e8496a25..a2966efb 100644 --- a/linux-core/drm_lock.c +++ b/linux-core/drm_lock.c @@ -105,14 +105,19 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  		  ret ? "interrupted" : "has lock");  	if (ret) return ret; -	sigemptyset(&dev->sigmask); -	sigaddset(&dev->sigmask, SIGSTOP); -	sigaddset(&dev->sigmask, SIGTSTP); -	sigaddset(&dev->sigmask, SIGTTIN); -	sigaddset(&dev->sigmask, SIGTTOU); -	dev->sigdata.context = lock->context; -	dev->sigdata.lock = dev->lock.hw_lock; -	block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +	/* don't set the block all signals on the master process for now  +	 * really probably not the correct answer but lets us debug xkb + 	 * xserver for now */ +	if (!file_priv->master) { +		sigemptyset(&dev->sigmask); +		sigaddset(&dev->sigmask, SIGSTOP); +		sigaddset(&dev->sigmask, SIGTSTP); +		sigaddset(&dev->sigmask, SIGTTIN); +		sigaddset(&dev->sigmask, SIGTTOU); +		dev->sigdata.context = lock->context; +		dev->sigdata.lock = dev->lock.hw_lock; +		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); +	}  	if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))  		dev->driver->dma_ready(dev); diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c index 4b494f9c..b90fc020 100644 --- a/linux-core/drm_memory.c +++ b/linux-core/drm_memory.c @@ -350,6 +350,15 @@ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)  }  EXPORT_SYMBOL_GPL(drm_core_ioremap); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev) +{ +	map->handle = ioremap_wc(map->offset, map->size); +} +EXPORT_SYMBOL_GPL(drm_core_ioremap_wc); +#endif +  void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)  {  	if (!map->handle || !map->size) diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 8eec336b..e0eb6335 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -63,211 +63,9 @@ static struct drm_bo_driver i915_bo_driver = {  };  #endif -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_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++) -		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 <= 0x14; i++) -		dev_priv->saveAR[i] = i915_read_ar(st01, i, 0); -	inb(st01); -	outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX); -	inb(st01); - -	/* 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 */ -	inb(st01); /* switch back to index mode */ -	for (i = 0; i <= 0x14; 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); -	inb(st01); - -	/* 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, pm_message_t state)  {  	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); @@ -279,122 +77,10 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)  		return 0;  	pci_save_state(dev->pdev); -	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); - -	/* Display arbitration control */ -	dev_priv->saveDSPARB = I915_READ(DSPARB); - -	/* Pipe & plane A info */ -	dev_priv->savePIPEACONF = I915_READ(PIPEACONF); -	dev_priv->savePIPEASRC = I915_READ(PIPEASRC); -	dev_priv->saveFPA0 = I915_READ(FPA0); -	dev_priv->saveFPA1 = I915_READ(FPA1); -	dev_priv->saveDPLL_A = I915_READ(DPLL_A); -	if (IS_I965G(dev)) -		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); -	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); -	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); -	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A); -	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); -	if (IS_I965G(dev)) { -		dev_priv->saveDSPASURF = I915_READ(DSPASURF); -		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); -	} -	i915_save_palette(dev, PIPE_A); -	dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT); - -	/* 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) || IS_IGD_GM(dev)) { -		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); -		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); -	} -	i915_save_palette(dev, PIPE_B); -	dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT); -	/* CRT state */ -	dev_priv->saveADPA = I915_READ(ADPA); +	i915_save_state(dev); -	/* 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); - -	/* Interrupt state */ -	dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R); -	dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R); -	dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R); - -	/* 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); - -	/* Clock gating state */ -	dev_priv->saveD_STATE = I915_READ(D_STATE); -	dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); - -	/* Cache mode state */ -	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); - -	/* Memory Arbitration state */ -	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); - -	/* 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)); -	} -	for (i = 0; i < 3; i++) -		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); - -	i915_save_vga(dev); +	intel_opregion_free(dev);  	if (state.event == PM_EVENT_SUSPEND) {  		/* Shut down the device */ @@ -407,154 +93,15 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)  static int i915_resume(struct drm_device *dev)  { -	struct drm_i915_private *dev_priv = dev->dev_private; -	int i; -  	pci_set_power_state(dev->pdev, PCI_D0);  	pci_restore_state(dev->pdev);  	if (pci_enable_device(dev->pdev))  		return -1; +	pci_set_master(dev->pdev); -	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); - -	I915_WRITE(DSPARB, dev_priv->saveDSPARB); - -	/* 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); -		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); -	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); - -	/* 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); -	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_restore_palette(dev, PIPE_A); -	/* Enable the plane */ -	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); -	I915_WRITE(DSPABASE, I915_READ(DSPABASE)); - -	/* 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); - -	/* 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_B); -	/* Enable the plane */ -	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); -	I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); - -	/* 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); - -	/* Clock gating state */ -	I915_WRITE (D_STATE, dev_priv->saveD_STATE); -	I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D); - -	/* Cache mode state */ -	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); - -	/* Memory arbitration state */ -	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); - -	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_restore_state(dev); -	i915_restore_vga(dev); +	intel_opregion_init(dev);  	return 0;  } diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index e403be6a..45613c3a 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -46,7 +46,7 @@ static inline void i915_initiate_rwflush(struct drm_i915_private *dev_priv,  		dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);  		dev_priv->flush_flags = fc->pending_flush;  		dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0); -		I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21)); +		I915_WRITE(INSTPM, (1 << 5) | (1 << 21));  		dev_priv->flush_pending = 1;  		fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW;  	} diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 593302ef..4c167d29 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -561,11 +561,11 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)  		dev_priv->mm.next_gem_seqno++;  	BEGIN_LP_RING(4); -	OUT_RING(CMD_STORE_DWORD_IDX); -	OUT_RING(I915_GEM_HWS_INDEX << STORE_DWORD_INDEX_SHIFT); +	OUT_RING(MI_STORE_DWORD_INDEX); +	OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);  	OUT_RING(seqno); -	OUT_RING(GFX_OP_USER_INTERRUPT); +	OUT_RING(MI_USER_INTERRUPT);  	ADVANCE_LP_RING();  	DRM_DEBUG("%d\n", seqno); @@ -591,7 +591,7 @@ uint32_t  i915_retire_commands(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; -	uint32_t cmd = CMD_MI_FLUSH | MI_NO_WRITE_FLUSH; +	uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;  	uint32_t flush_domains = 0;  	RING_LOCALS; @@ -818,7 +818,7 @@ i915_gem_flush(struct drm_device *dev,  		 * are flushed at any MI_FLUSH.  		 */ -		cmd = CMD_MI_FLUSH | MI_NO_WRITE_FLUSH; +		cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;  		if ((invalidate_domains|flush_domains) &  		    I915_GEM_DOMAIN_RENDER)  			cmd &= ~MI_NO_WRITE_FLUSH; @@ -2381,14 +2381,14 @@ i915_gem_init_ringbuffer(struct drm_device *dev)  	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;  	/* Stop the ring if it's running. */ -	I915_WRITE(LP_RING + RING_LEN, 0); -	I915_WRITE(LP_RING + RING_HEAD, 0); -	I915_WRITE(LP_RING + RING_TAIL, 0); -	I915_WRITE(LP_RING + RING_START, 0); +	I915_WRITE(PRB0_CTL, 0); +	I915_WRITE(PRB0_HEAD, 0); +	I915_WRITE(PRB0_TAIL, 0); +	I915_WRITE(PRB0_START, 0);  	/* Initialize the ring. */ -	I915_WRITE(LP_RING + RING_START, obj_priv->gtt_offset); -	I915_WRITE(LP_RING + RING_LEN, +	I915_WRITE(PRB0_START, obj_priv->gtt_offset); +	I915_WRITE(PRB0_CTL,  		   ((obj->size - 4096) & RING_NR_PAGES) |  		   RING_NO_REPORT |  		   RING_VALID); diff --git a/linux-core/i915_gem_proc.c b/linux-core/i915_gem_proc.c index 90351ac7..132eb3d1 100644 --- a/linux-core/i915_gem_proc.c +++ b/linux-core/i915_gem_proc.c @@ -220,15 +220,15 @@ static int i915_interrupt_info(char *buf, char **start, off_t offset,  	*start = &buf[offset];  	*eof = 0;  	DRM_PROC_PRINT("Interrupt enable:    %08x\n", -		       I915_READ(I915REG_INT_ENABLE_R)); +		       I915_READ(IER));  	DRM_PROC_PRINT("Interrupt identity:  %08x\n", -		       I915_READ(I915REG_INT_IDENTITY_R)); +		       I915_READ(IIR));  	DRM_PROC_PRINT("Interrupt mask:      %08x\n", -		       I915_READ(I915REG_INT_MASK_R)); +		       I915_READ(IMR));  	DRM_PROC_PRINT("Pipe A stat:         %08x\n", -		       I915_READ(I915REG_PIPEASTAT)); +		       I915_READ(PIPEASTAT));  	DRM_PROC_PRINT("Pipe B stat:         %08x\n", -		       I915_READ(I915REG_PIPEBSTAT)); +		       I915_READ(PIPEBSTAT));  	DRM_PROC_PRINT("Interrupts received: %d\n",  		       atomic_read(&dev_priv->irq_received));  	DRM_PROC_PRINT("Current sequence:    %d\n", diff --git a/linux-core/i915_opregion.c b/linux-core/i915_opregion.c new file mode 100644 index 00000000..015376f8 --- /dev/null +++ b/linux-core/i915_opregion.c @@ -0,0 +1,387 @@ +/* + * + * Copyright 2008 Intel Corporation <hong.liu@intel.com> + * Copyright 2008 Red Hat <mjg@redhat.com> + * + * 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, sub license, 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 + * NON-INFRINGEMENT.  IN NO EVENT SHALL INTEL 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. + * + */ + +#include <linux/acpi.h> + +#include "drmP.h" +#include "i915_drm.h" +#include "i915_drv.h" + +#define PCI_ASLE 0xe4 +#define PCI_ASLS 0xfc + +#define OPREGION_SZ            (8*1024) +#define OPREGION_HEADER_OFFSET 0 +#define OPREGION_ACPI_OFFSET   0x100 +#define OPREGION_SWSCI_OFFSET  0x200 +#define OPREGION_ASLE_OFFSET   0x300 +#define OPREGION_VBT_OFFSET    0x1000 + +#define OPREGION_SIGNATURE "IntelGraphicsMem" +#define MBOX_ACPI      (1<<0) +#define MBOX_SWSCI     (1<<1) +#define MBOX_ASLE      (1<<2) + +/* _DOD id definitions */ +#define OUTPUT_CONNECTOR_MSK   0xf000 +#define OUTPUT_CONNECTOR_OFFSET        12 + +#define OUTPUT_PORT_MSK                0x00f0 +#define OUTPUT_PORT_OFFSET     4 +  #define OUTPUT_PORT_ANALOG   0 +  #define OUTPUT_PORT_LVDS     1 +  #define OUTPUT_PORT_SDVOB    2 +  #define OUTPUT_PORT_SDVOC    3 +  #define OUTPUT_PORT_TV       4 + +#define OUTPUT_DISPLAY_MSK     0x0f00 +#define OUTPUT_DISPLAY_OFFSET  8 +  #define OUTPUT_DISPLAY_OTHER         0 +  #define OUTPUT_DISPLAY_VGA           1 +  #define OUTPUT_DISPLAY_TV            2 +  #define OUTPUT_DISPLAY_DIGI          3 +  #define OUTPUT_DISPLAY_FLAT_PANEL    4 + +/* predefined id for integrated LVDS and VGA connector */ +#define OUTPUT_INT_LVDS        0x00000110 +#define OUTPUT_INT_VGA 0x80000100 + +struct opregion_header { +       u8 signature[16]; +       u32 size; +       u32 opregion_ver; +       u8 bios_ver[32]; +       u8 vbios_ver[16]; +       u8 driver_ver[16]; +       u32 mboxes; +       u8 reserved[164]; +} __attribute__((packed)); + +/* OpRegion mailbox #1: public ACPI methods */ +struct opregion_acpi { +       u32 drdy;       /* driver readiness */ +       u32 csts;       /* notification status */ +       u32 cevt;       /* current event */ +       u8 rsvd1[20]; +       u32 didl[8];    /* supported display devices ID list */ +       u32 cpdl[8];    /* currently presented display list */ +       u32 cadl[8];    /* currently active display list */ +       u32 nadl[8];    /* next active devices list */ +       u32 aslp;       /* ASL sleep time-out */ +       u32 tidx;       /* toggle table index */ +       u32 chpd;       /* current hotplug enable indicator */ +       u32 clid;       /* current lid state*/ +       u32 cdck;       /* current docking state */ +       u32 sxsw;       /* Sx state resume */ +       u32 evts;       /* ASL supported events */ +       u32 cnot;       /* current OS notification */ +       u32 nrdy;       /* driver status */ +       u8 rsvd2[60]; +} __attribute__((packed)); + +/* OpRegion mailbox #2: SWSCI */ +struct opregion_swsci { +       u32 scic;       /* SWSCI command|status|data */ +       u32 parm;       /* command parameters */ +       u32 dslp;       /* driver sleep time-out */ +       u8 rsvd[244]; +} __attribute__((packed)); + +/* OpRegion mailbox #3: ASLE */ +struct opregion_asle { +       u32 ardy;       /* driver readiness */ +       u32 aslc;       /* ASLE interrupt command */ +       u32 tche;       /* technology enabled indicator */ +       u32 alsi;       /* current ALS illuminance reading */ +       u32 bclp;       /* backlight brightness to set */ +       u32 pfit;       /* panel fitting state */ +       u32 cblv;       /* current brightness level */ +       u16 bclm[20];   /* backlight level duty cycle mapping table */ +       u32 cpfm;       /* current panel fitting mode */ +       u32 epfm;       /* enabled panel fitting modes */ +       u8 plut[74];    /* panel LUT and identifier */ +       u32 pfmb;       /* PWM freq and min brightness */ +       u8 rsvd[102]; +} __attribute__((packed)); + +/* ASLE irq request bits */ +#define ASLE_SET_ALS_ILLUM     (1 << 0) +#define ASLE_SET_BACKLIGHT     (1 << 1) +#define ASLE_SET_PFIT          (1 << 2) +#define ASLE_SET_PWM_FREQ      (1 << 3) +#define ASLE_REQ_MSK           0xf + +/* response bits of ASLE irq request */ +#define ASLE_ALS_ILLUM_FAIL    (2<<10) +#define ASLE_BACKLIGHT_FAIL    (2<<12) +#define ASLE_PFIT_FAIL         (2<<14) +#define ASLE_PWM_FREQ_FAIL     (2<<16) + +/* ASLE backlight brightness to set */ +#define ASLE_BCLP_VALID                (1<<31) +#define ASLE_BCLP_MSK          (~(1<<31)) + +/* ASLE panel fitting request */ +#define ASLE_PFIT_VALID         (1<<31) +#define ASLE_PFIT_CENTER (1<<0) +#define ASLE_PFIT_STRETCH_TEXT (1<<1) +#define ASLE_PFIT_STRETCH_GFX (1<<2) + +/* PWM frequency and minimum brightness */ +#define ASLE_PFMB_BRIGHTNESS_MASK (0xff) +#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8) +#define ASLE_PFMB_PWM_MASK (0x7ffffe00) +#define ASLE_PFMB_PWM_VALID (1<<31) + +#define ASLE_CBLV_VALID         (1<<31) + +static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct opregion_asle *asle = dev_priv->opregion.asle; +	u32 blc_pwm_ctl; +	 +	if (!(bclp & ASLE_BCLP_VALID)) +		return ASLE_BACKLIGHT_FAIL; +	 +	bclp &= ASLE_BCLP_MSK; +	if (bclp < 0 || bclp > 255) +		return ASLE_BACKLIGHT_FAIL; +	 +	blc_pwm_ctl = I915_READ(BLC_PWM_CTL); +	blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; +	I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | ((bclp * 0x101) -1)); +	asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; +	 +	return 0; +} + +static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) +{ +	return 0; +} + +static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	if (pfmb & ASLE_PFMB_PWM_VALID) { +		u32 blc_pwm_ctl = I915_READ(BLC_PWM_CTL); +		u32 pwm = pfmb & ASLE_PFMB_PWM_MASK; +		blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK; +		pwm = pwm >> 9; +		// FIXME - what do we do with the PWM? +	} +	return 0; +} + +static u32 asle_set_pfit(struct drm_device *dev, u32 pfit) +{ +	if (!(pfit & ASLE_PFIT_VALID)) +		return ASLE_PFIT_FAIL; +	return 0; +} + +void opregion_asle_intr(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct opregion_asle *asle = dev_priv->opregion.asle; +	u32 asle_stat = 0; +	u32 asle_req; + +	if (!asle) +		return; + +	asle_req = asle->aslc & ASLE_REQ_MSK; +	 +	if (!asle_req) { +		DRM_DEBUG("non asle set request??\n"); +		return; +	} + +	if (asle_req & ASLE_SET_ALS_ILLUM) +		asle_stat |= asle_set_als_illum(dev, asle->alsi); +	 +	if (asle_req & ASLE_SET_BACKLIGHT) +		asle_stat |= asle_set_backlight(dev, asle->bclp); +	 +	if (asle_req & ASLE_SET_PFIT) +		asle_stat |= asle_set_pfit(dev, asle->pfit); +	 +	if (asle_req & ASLE_SET_PWM_FREQ) +		asle_stat |= asle_set_pwm_freq(dev, asle->pfmb); +	 +	asle->aslc = asle_stat; +} + +#define ASLE_ALS_EN    (1<<0) +#define ASLE_BLC_EN    (1<<1) +#define ASLE_PFIT_EN   (1<<2) +#define ASLE_PFMB_EN   (1<<3) + +void opregion_enable_asle(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct opregion_asle *asle = dev_priv->opregion.asle; + +	if (asle) { +		if (IS_MOBILE(dev)) { +			u32 pipeb_stats = I915_READ(PIPEBSTAT); +			/* Some hardware uses the legacy backlight controller +			   to signal interrupts, so we need to set up pipe B +			   to generate an IRQ on writes */ +			pipeb_stats |= I915_LEGACY_BLC_EVENT_ENABLE; +			I915_WRITE(PIPEBSTAT, pipeb_stats); + +			dev_priv->irq_mask_reg &= +				~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; +		} + +		dev_priv->irq_mask_reg &= ~I915_ASLE_INTERRUPT; + +		asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |  +			ASLE_PFMB_EN; +		asle->ardy = 1; +	} +} + +#define ACPI_EV_DISPLAY_SWITCH (1<<0) +#define ACPI_EV_LID            (1<<1) +#define ACPI_EV_DOCK           (1<<2) + +static struct intel_opregion *system_opregion; + +int intel_opregion_video_event(struct notifier_block *nb, unsigned long val, +                               void *data) +{ +	/* The only video events relevant to opregion are 0x80. These indicate +	   either a docking event, lid switch or display switch request. In +	   Linux, these are handled by the dock, button and video drivers. +	   We might want to fix the video driver to be opregion-aware in +	   future, but right now we just indicate to the firmware that the +	   request has been handled */ +	 +	struct opregion_acpi *acpi; + +	if (!system_opregion) +		return NOTIFY_DONE; +	 +	acpi = system_opregion->acpi; +	acpi->csts = 0; + +	return NOTIFY_OK; +} + +static struct notifier_block intel_opregion_notifier = { +	.notifier_call = intel_opregion_video_event, +}; + +int intel_opregion_init(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_opregion *opregion = &dev_priv->opregion; +	void *base; +	u32 asls, mboxes; +	int err = 0; +	 +	pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); +	DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls); +	if (asls == 0) { +		DRM_DEBUG("ACPI OpRegion not supported!\n"); +		return -ENOTSUPP; +	} +	 +	base = ioremap(asls, OPREGION_SZ); +	if (!base) +		return -ENOMEM; +	 +	opregion->header = base; +	if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { +		DRM_DEBUG("opregion signature mismatch\n"); +		err = -EINVAL; +		goto err_out; +	} +	 +	mboxes = opregion->header->mboxes; +	if (mboxes & MBOX_ACPI) { +		DRM_DEBUG("Public ACPI methods supported\n"); +		opregion->acpi = base + OPREGION_ACPI_OFFSET; +	} else { +		DRM_DEBUG("Public ACPI methods not supported\n"); +		err = -ENOTSUPP; +		goto err_out; +	} +	opregion->enabled = 1; +	 +	if (mboxes & MBOX_SWSCI) { +		DRM_DEBUG("SWSCI supported\n"); +		opregion->swsci = base + OPREGION_SWSCI_OFFSET; +	} +	if (mboxes & MBOX_ASLE) { +		DRM_DEBUG("ASLE supported\n"); +		opregion->asle = base + OPREGION_ASLE_OFFSET; +	} +	 +	/* Notify BIOS we are ready to handle ACPI video ext notifs. +	 * Right now, all the events are handled by the ACPI video module. +	 * We don't actually need to do anything with them. */ +	opregion->acpi->csts = 0; +	opregion->acpi->drdy = 1; + +	system_opregion = opregion; +	register_acpi_notifier(&intel_opregion_notifier); +	 +	return 0; +	 +err_out: +	iounmap(opregion->header); +	opregion->header = NULL; +	return err; +} + +void intel_opregion_free(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_opregion *opregion = &dev_priv->opregion; +	 +	if (!opregion->enabled) +		return; +	 +	opregion->acpi->drdy = 0; +	 +	system_opregion = NULL; +	unregister_acpi_notifier(&intel_opregion_notifier); +	 +	/* just clear all opregion memory pointers now */ +	iounmap(opregion->header); +	opregion->header = NULL; +	opregion->acpi = NULL; +	opregion->swsci = NULL; +	opregion->asle = NULL; +	 +	opregion->enabled = 0; +} diff --git a/linux-core/i915_suspend.c b/linux-core/i915_suspend.c new file mode 120000 index 00000000..b55754c5 --- /dev/null +++ b/linux-core/i915_suspend.c @@ -0,0 +1 @@ +../shared-core/i915_suspend.c
\ No newline at end of file diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index f0f3320e..934fa0b9 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -52,6 +52,28 @@ static int dri_library_name(struct drm_device * dev, char * buf)  		"r300"));  } +static int radeon_suspend(struct drm_device *dev, pm_message_t state) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	/* Disable *all* interrupts */ +	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) +		RADEON_WRITE(R500_DxMODE_INT_MASK, 0); +	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); +	return 0; +} + +static int radeon_resume(struct drm_device *dev) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	/* Restore interrupt registers */ +	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) +		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); +	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); +	return 0; +} +  static struct pci_device_id pciidlist[] = {  	radeon_PCI_IDS  }; @@ -69,6 +91,8 @@ static struct drm_driver driver = {  	.postclose = radeon_driver_postclose,  	.lastclose = radeon_driver_lastclose,  	.unload = radeon_driver_unload, +	.suspend = radeon_suspend, +	.resume = radeon_resume,  	.get_vblank_counter = radeon_get_vblank_counter,  	.enable_vblank = radeon_enable_vblank,  	.disable_vblank = radeon_disable_vblank, diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 64401ae5..423208b0 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -135,7 +135,7 @@ int xgi_submit_cmdlist(struct drm_device * dev, void * data,  		DRM_DEBUG("info->cmdring.last_ptr != NULL\n");  		if (pCmdInfo->type == BTYPE_3D) { -			xgi_emit_flush(info, FALSE); +			xgi_emit_flush(info, false);  		}  		info->cmdring.last_ptr[1] = cpu_to_le32(begin[1]); @@ -148,7 +148,9 @@ int xgi_submit_cmdlist(struct drm_device * dev, void * data,  	}  	info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr); +#ifdef XGI_HAVE_FENCE  	drm_fence_flush_old(info->dev, 0, info->next_sequence); +#endif /* XGI_HAVE_FENCE */  	return 0;  } @@ -214,7 +216,7 @@ void xgi_cmdlist_cleanup(struct xgi_info * info)  		 * list chain with a flush command.  		 */  		if (info->cmdring.last_ptr != NULL) { -			xgi_emit_flush(info, FALSE); +			xgi_emit_flush(info, false);  			xgi_emit_nop(info);  		} @@ -322,5 +324,5 @@ void xgi_emit_irq(struct xgi_info * info)  	if (info->cmdring.last_ptr == NULL)  		return; -	xgi_emit_flush(info, TRUE); +	xgi_emit_flush(info, true);  } diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index f0225f89..bfe9acdf 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -37,7 +37,9 @@ static struct pci_device_id pciidlist[] = {  	xgi_PCI_IDS  }; +#ifdef XGI_HAVE_FENCE  extern struct drm_fence_driver xgi_fence_driver; +#endif /* XGI_HAVE_FENCE */  int xgi_bootstrap(struct drm_device *, void *, struct drm_file *); @@ -47,6 +49,8 @@ static struct drm_ioctl_desc xgi_ioctls[] = {  	DRM_IOCTL_DEF(DRM_XGI_FREE, xgi_free_ioctl, DRM_AUTH),  	DRM_IOCTL_DEF(DRM_XGI_SUBMIT_CMDLIST, xgi_submit_cmdlist, DRM_AUTH),  	DRM_IOCTL_DEF(DRM_XGI_STATE_CHANGE, xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER), +	DRM_IOCTL_DEF(DRM_XGI_SET_FENCE, xgi_set_fence_ioctl, DRM_AUTH), +	DRM_IOCTL_DEF(DRM_XGI_WAIT_FENCE, xgi_wait_fence_ioctl, DRM_AUTH),  };  static const int xgi_max_ioctl = DRM_ARRAY_SIZE(xgi_ioctls); @@ -58,6 +62,7 @@ static void xgi_driver_lastclose(struct drm_device * dev);  static void xgi_reclaim_buffers_locked(struct drm_device * dev,  	struct drm_file * filp);  static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS); +static int xgi_kern_isr_postinstall(struct drm_device * dev);  static struct drm_driver driver = { @@ -70,7 +75,7 @@ static struct drm_driver driver = {  	.lastclose = xgi_driver_lastclose,  	.dma_quiescent = NULL,  	.irq_preinstall = NULL, -	.irq_postinstall = NULL, +	.irq_postinstall = xgi_kern_isr_postinstall,  	.irq_uninstall = NULL,  	.irq_handler = xgi_kern_isr,  	.reclaim_buffers = drm_core_reclaim_buffers, @@ -100,7 +105,9 @@ static struct drm_driver driver = {  		.remove = __devexit_p(drm_cleanup_pci),  	}, +#ifdef XGI_HAVE_FENCE  	.fence_driver = &xgi_fence_driver, +#endif /* XGI_HAVE_FENCE */  	.name = DRIVER_NAME,  	.desc = DRIVER_DESC, @@ -307,8 +314,8 @@ void xgi_driver_lastclose(struct drm_device * dev)  		    || info->pcie_heap_initialized) {  			drm_sman_cleanup(&info->sman); -			info->fb_heap_initialized = FALSE; -			info->pcie_heap_initialized = FALSE; +			info->fb_heap_initialized = false; +			info->pcie_heap_initialized = false;  		}  	}  } @@ -355,7 +362,10 @@ irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS)  		DRM_WRITE32(info->mmio_map,  			    0x2800 + M2REG_AUTO_LINK_SETTING_ADDRESS,  			    cpu_to_le32(M2REG_AUTO_LINK_SETTING_COMMAND | irq_bits)); +#ifdef XGI_HAVE_FENCE  		xgi_fence_handler(dev); +#endif /* XGI_HAVE_FENCE */ +		DRM_WAKEUP(&info->fence_queue);  		return IRQ_HANDLED;  	} else {  		return IRQ_NONE; @@ -363,6 +373,15 @@ irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS)  } +int xgi_kern_isr_postinstall(struct drm_device * dev) +{ +	struct xgi_info *info = dev->dev_private; + +	DRM_INIT_WAITQUEUE(&info->fence_queue); +	return 0; +} + +  int xgi_driver_load(struct drm_device *dev, unsigned long flags)  {  	struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 9408073e..5ad3ddb3 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -35,11 +35,11 @@  #define DRIVER_NAME		"xgi"  #define DRIVER_DESC		"XGI XP5 / XP10 / XG47" -#define DRIVER_DATE		"20071003" +#define DRIVER_DATE		"20080612"  #define DRIVER_MAJOR		1 -#define DRIVER_MINOR		1 -#define DRIVER_PATCHLEVEL	3 +#define DRIVER_MINOR		2 +#define DRIVER_PATCHLEVEL	0  #include "xgi_cmdlist.h"  #include "xgi_drm.h" @@ -74,6 +74,7 @@ struct xgi_info {  	struct xgi_cmdring_info cmdring;  	DRM_SPINTYPE fence_lock; +	wait_queue_head_t fence_queue;  	unsigned complete_sequence;  	unsigned next_sequence;  }; @@ -86,7 +87,7 @@ extern int xgi_fb_heap_init(struct xgi_info * info);  extern int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,  	struct drm_file * filp); -extern int xgi_free(struct xgi_info * info, unsigned long index, +extern int xgi_free(struct xgi_info * info, unsigned int index,  	struct drm_file * filp);  extern int xgi_pcie_heap_init(struct xgi_info * info); @@ -98,12 +99,24 @@ extern void xgi_disable_mmio(struct xgi_info * info);  extern void xgi_enable_ge(struct xgi_info * info);  extern void xgi_disable_ge(struct xgi_info * info); +/* TTM-style fences. + */ +#ifdef XGI_HAVE_FENCE  extern void xgi_poke_flush(struct drm_device * dev, uint32_t class);  extern int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class,  	uint32_t flags, uint32_t * sequence, uint32_t * native_type);  extern void xgi_fence_handler(struct drm_device * dev);  extern int xgi_fence_has_irq(struct drm_device *dev, uint32_t class,  	uint32_t flags); +#endif /* XGI_HAVE_FENCE */ + + +/* Non-TTM-style fences. + */ +extern int xgi_set_fence_ioctl(struct drm_device * dev, void * data, +	struct drm_file * filp); +extern int xgi_wait_fence_ioctl(struct drm_device * dev, void * data, +	struct drm_file * filp);  extern int xgi_alloc_ioctl(struct drm_device * dev, void * data,  	struct drm_file * filp); diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 3f50fe8f..e793bd3f 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -93,7 +93,7 @@ int xgi_alloc_ioctl(struct drm_device * dev, void * data,  } -int xgi_free(struct xgi_info * info, unsigned long index, +int xgi_free(struct xgi_info * info, unsigned int index,  	     struct drm_file * filp)  {  	int err; @@ -111,7 +111,7 @@ int xgi_free_ioctl(struct drm_device * dev, void * data,  {  	struct xgi_info *info = dev->dev_private; -	return xgi_free(info, *(unsigned long *) data, filp); +	return xgi_free(info, *(unsigned int *) data, filp);  } diff --git a/linux-core/xgi_fence.c b/linux-core/xgi_fence.c index 63ed29ee..38cf9e4f 100644 --- a/linux-core/xgi_fence.c +++ b/linux-core/xgi_fence.c @@ -30,6 +30,76 @@  #include "xgi_misc.h"  #include "xgi_cmdlist.h" +static int xgi_low_level_fence_emit(struct drm_device *dev, u32 *sequence) +{ +	struct xgi_info *const info = dev->dev_private; + +	if (info == NULL) { +		DRM_ERROR("called with no initialization\n"); +		return -EINVAL; +	} + +	DRM_SPINLOCK(&info->fence_lock); +	info->next_sequence++; +	if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) { +		info->next_sequence = 1; +	} + +	*sequence = (u32) info->next_sequence; +	DRM_SPINUNLOCK(&info->fence_lock); + + +	xgi_emit_irq(info); +	return 0; +} + +#define GET_BEGIN_ID(i) (le32_to_cpu(DRM_READ32((i)->mmio_map, 0x2820)) \ +				 & BEGIN_BEGIN_IDENTIFICATION_MASK) + +static int xgi_low_level_fence_wait(struct drm_device *dev, unsigned *sequence) +{ +	struct xgi_info *const info = dev->dev_private; +	unsigned int cur_fence; +	int ret = 0; + +	if (info == NULL) { +		DRM_ERROR("called with no initialization\n"); +		return -EINVAL; +	} + +	/* Assume that the user has missed the current sequence number +	 * by about a day rather than she wants to wait for years +	 * using fences. +	 */ +	DRM_WAIT_ON(ret, info->fence_queue, 3 * DRM_HZ, +		    ((((cur_fence = GET_BEGIN_ID(info)) +		      - *sequence) & BEGIN_BEGIN_IDENTIFICATION_MASK) +		     <= (1 << 18))); + +	info->complete_sequence = cur_fence; +	*sequence = cur_fence; + +	return ret; +} + + +int xgi_set_fence_ioctl(struct drm_device * dev, void * data, +			struct drm_file * filp) +{ +	(void) filp; +	return xgi_low_level_fence_emit(dev, (u32 *) data); +} + + +int xgi_wait_fence_ioctl(struct drm_device * dev, void * data, +			 struct drm_file * filp) +{ +	(void) filp; +	return xgi_low_level_fence_wait(dev, (u32 *) data); +} + + +#ifdef XGI_HAVE_FENCE  static void xgi_fence_poll(struct drm_device * dev, uint32_t class,   			   uint32_t waiting_types)  { @@ -68,25 +138,18 @@ int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class,  			    uint32_t flags, uint32_t * sequence,  			    uint32_t * native_type)  { -	struct xgi_info * info = dev->dev_private; +	int err; -	if ((info == NULL) || (class != 0)) -		return -EINVAL; - - -	DRM_SPINLOCK(&info->fence_lock); -	info->next_sequence++; -	if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) { -		info->next_sequence = 1; -	} -	DRM_SPINUNLOCK(&info->fence_lock); +	(void) flags; +	if (class != 0) +		return -EINVAL; -	xgi_emit_irq(info); +	err = xgi_low_level_fence_emit(dev, sequence); +	if (err) +		return err; -	*sequence = (uint32_t) info->next_sequence;  	*native_type = DRM_FENCE_TYPE_EXE; -  	return 0;  } @@ -120,3 +183,4 @@ struct drm_fence_driver xgi_fence_driver = {  	.wait = NULL  }; +#endif /* XGI_HAVE_FENCE */ diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 2b3a1788..2a9632f6 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -46,41 +46,41 @@ static bool xgi_validate_signal(struct drm_map * map)  		check = le16_to_cpu(DRM_READ16(map, 0x2360));  		if ((check & 0x3f) != ((check & 0x3f00) >> 8)) { -			return FALSE; +			return false;  		}  		/* Check RO channel */  		DRM_WRITE8(map, 0x235c, 0x83);  		check = le16_to_cpu(DRM_READ16(map, 0x2360));  		if ((check & 0x0f) != ((check & 0xf0) >> 4)) { -			return FALSE; +			return false;  		}  		/* Check RW channel */  		DRM_WRITE8(map, 0x235c, 0x88);  		check = le16_to_cpu(DRM_READ16(map, 0x2360));  		if ((check & 0x0f) != ((check & 0xf0) >> 4)) { -			return FALSE; +			return false;  		}  		/* Check RO channel outstanding */  		DRM_WRITE8(map, 0x235c, 0x8f);  		check = le16_to_cpu(DRM_READ16(map, 0x2360));  		if (0 != (check & 0x3ff)) { -			return FALSE; +			return false;  		}  		/* Check RW channel outstanding */  		DRM_WRITE8(map, 0x235c, 0x90);  		check = le16_to_cpu(DRM_READ16(map, 0x2360));  		if (0 != (check & 0x3ff)) { -			return FALSE; +			return false;  		}  		/* No pending PCIE request. GE stall. */  	} -	return TRUE; +	return true;  } @@ -138,7 +138,7 @@ static void xgi_ge_hang_reset(struct drm_map * map)  bool xgi_ge_irq_handler(struct xgi_info * info)  {  	const u32 int_status = le32_to_cpu(DRM_READ32(info->mmio_map, 0x2810)); -	bool is_support_auto_reset = FALSE; +	bool is_support_auto_reset = false;  	/* Check GE on/off */  	if (0 == (0xffffc0f0 & int_status)) { @@ -179,15 +179,15 @@ bool xgi_ge_irq_handler(struct xgi_info * info)  				    cpu_to_le32((int_status & ~0x01) | 0x04000000));  		} -		return TRUE; +		return true;  	} -	return FALSE; +	return false;  }  bool xgi_crt_irq_handler(struct xgi_info * info)  { -	bool ret = FALSE; +	bool ret = false;  	u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);  	/* CRT1 interrupt just happened @@ -205,7 +205,7 @@ bool xgi_crt_irq_handler(struct xgi_info * info)  		op3cf_3d = IN3CFB(info->mmio_map, 0x3d);  		OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));  		OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04)); -		ret = TRUE; +		ret = true;  	}  	DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce); @@ -214,7 +214,7 @@ bool xgi_crt_irq_handler(struct xgi_info * info)  bool xgi_dvi_irq_handler(struct xgi_info * info)  { -	bool ret = FALSE; +	bool ret = false;  	const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);  	/* DVI interrupt just happened @@ -242,7 +242,7 @@ bool xgi_dvi_irq_handler(struct xgi_info * info)  		OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01));  		OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01)); -		ret = TRUE; +		ret = true;  	}  	DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);  | 
