diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/Makefile.kernel | 5 | ||||
| -rw-r--r-- | linux-core/drmP.h | 15 | ||||
| -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 | 142 | ||||
| -rw-r--r-- | linux-core/drm_memory.c | 9 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 272 | ||||
| -rw-r--r-- | linux-core/i915_opregion.c | 390 | ||||
| l--------- | linux-core/i915_suspend.c | 1 | ||||
| -rw-r--r-- | linux-core/radeon_drv.c | 24 | ||||
| -rw-r--r-- | linux-core/radeon_reg.h | 33 | ||||
| -rw-r--r-- | linux-core/xgi_cmdlist.c | 2 | ||||
| -rw-r--r-- | linux-core/xgi_drv.c | 21 | ||||
| -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 | 
16 files changed, 663 insertions, 380 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index d3668dfb..b09697d3 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -21,10 +21,11 @@ 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_execbuf.o i915_gem.o \ +		i915_buffer.o i915_compat.o i915_execbuf.o i915_suspend.o \ +		i915_gem.o i915_opregion.o \  	        intel_display.o intel_crt.o intel_lvds.o intel_bios.o \  		intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o \ -		intel_tv.o i915_compat.o intel_dvo.o dvo_ch7xxx.o \ +		intel_tv.o intel_dvo.o dvo_ch7xxx.o \  		dvo_ch7017.o dvo_ivch.o dvo_tfp410.o dvo_sil164.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/drmP.h b/linux-core/drmP.h index e3a08e79..1e5838ee 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -962,6 +962,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; @@ -970,13 +978,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); @@ -1314,7 +1321,6 @@ extern int drm_wait_hotplug(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 void drm_handle_hotplug(struct drm_device *dev);  extern int drm_vblank_get(struct drm_device *dev, int crtc); @@ -1505,6 +1511,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_compat.h b/linux-core/drm_compat.h index 564a9438..08dd5f8d 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -394,4 +394,8 @@ extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,  	on_each_cpu(handler, data, wait, 1)  #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 9113fa54..36c0a14d 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -635,9 +635,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;  	} @@ -654,6 +655,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) @@ -679,7 +681,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 = -EFAULT; diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 0dfbe57a..800768ae 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;  		} @@ -118,13 +124,9 @@ static void drm_vblank_cleanup(struct drm_device *dev)  	    drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,  		 DRM_MEM_DRIVER); -	if (dev->vblank_premodeset) -	    drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * -		 dev->num_crtcs, DRM_MEM_DRIVER); - -	if (dev->vblank_offset) -	    drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs, -		 DRM_MEM_DRIVER); +	if (dev->vblank_inmodeset) +	    drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) * +		     dev->num_crtcs, DRM_MEM_DRIVER);  }  int drm_vblank_init(struct drm_device *dev, int num_crtcs) @@ -167,13 +169,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 */ @@ -184,6 +182,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: @@ -426,8 +426,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); @@ -440,10 +439,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;  	/* @@ -454,20 +458,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 @@ -475,9 +478,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. @@ -487,15 +488,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); @@ -525,13 +528,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) { @@ -539,14 +550,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; @@ -580,7 +605,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; @@ -601,7 +625,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) { @@ -611,7 +637,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) && @@ -644,15 +671,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) { @@ -675,23 +705,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;  } @@ -745,7 +775,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_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 33a33e61..a3b35358 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -272,7 +272,6 @@ static void i915_restore_vga(struct drm_device *dev)  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); @@ -284,122 +283,12 @@ 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->saveDSPAADDR = I915_READ(DSPAADDR); -	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(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->saveDSPBADDR = I915_READ(DSPBADDR); -	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(PIPEBSTAT); - -	/* 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->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); -	dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); -	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); - -	/* 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(IIR); -	dev_priv->saveIER = I915_READ(IER); -	dev_priv->saveIMR = I915_READ(IMR); - -	/* VGA state */ -	dev_priv->saveVGA0 = I915_READ(VGA0); -	dev_priv->saveVGA1 = I915_READ(VGA1); -	dev_priv->saveVGA_PD = I915_READ(VGA_PD); -	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); - -	/* Clock gating state */ -	dev_priv->saveD_STATE = I915_READ(D_STATE); -	dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS); - -	/* 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(SWF00 + (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); +	i915_save_state(dev); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +	intel_opregion_free(dev); +#endif  	if (state.event == PM_EVENT_SUSPEND) {  		/* Shut down the device */ @@ -412,158 +301,17 @@ 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); -	DRM_INFO("resuming i915\n"); - -	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); - -	I915_WRITE(DSPARB, dev_priv->saveDSPARB); +	i915_restore_state(dev); -	/* 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(DSPAADDR, dev_priv->saveDSPAADDR); -	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(DSPAADDR, I915_READ(DSPAADDR)); - -	/* Pipe & plane B info */ -	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { -		DRM_INFO("restoring DPLL_B: 0x%08x\n", dev_priv->saveDPLL_B); -		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); -	DRM_INFO("restoring DPLL_B: 0x%08x\n", 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(DSPBADDR, dev_priv->saveDSPBADDR); -	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(DSPBADDR, I915_READ(DSPBADDR)); - -	/* 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(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); -	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); -	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); -	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(VGA0, dev_priv->saveVGA0); -	I915_WRITE(VGA1, dev_priv->saveVGA1); -	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); -	udelay(150); - -	/* Clock gating state */ -	I915_WRITE (D_STATE, dev_priv->saveD_STATE); -	I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS); - -	/* 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(SWF00 + (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_vga(dev); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +	intel_opregion_init(dev); +#endif  	return 0;  } diff --git a/linux-core/i915_opregion.c b/linux-core/i915_opregion.c new file mode 100644 index 00000000..d015db28 --- /dev/null +++ b/linux-core/i915_opregion.c @@ -0,0 +1,390 @@ +/* + * + * 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" + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) +#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; +	u32 mask = 0; + +	if (asle) { +		u32 pipeb_stats = I915_READ(PIPEBSTAT); +		if (IS_MOBILE(dev)) { +			/* Some hardware uses the legacy backlight controller +			   to signal interrupts, so we need to set up pipe B +			   to generate an IRQ on writes */ +			I915_WRITE(PIPEBSTAT, pipeb_stats |=  +				   I915_LEGACY_BLC_EVENT_ENABLE); +			mask = I915_ASLE_INTERRUPT | +				I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; +		} else +			mask = I915_ASLE_INTERRUPT; +		 +		dev_priv->irq_mask_reg &= ~mask; + +		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; +} +#endif 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 5f51c813..7676ca4c 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -59,6 +59,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  }; @@ -94,6 +116,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/radeon_reg.h b/linux-core/radeon_reg.h index 9b6bf1ec..04cfa732 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -3953,7 +3953,6 @@  #       define R300_TILE_SIZE_32                        (2 << 4)  #       define R300_SUBPIXEL_1_12                       (0 << 16)  #       define R300_SUBPIXEL_1_16                       (1 << 16) -#define R300_GB_SELECT				        0x401c  #define R300_GB_ENABLE				        0x4008  #define R300_GB_AA_CONFIG				0x4020  #define R400_GB_PIPE_SELECT                             0x402c @@ -4031,17 +4030,6 @@  #       define R300_GL_CLIP_SPACE_DEF                   (0 << 22)  #       define R300_DX_CLIP_SPACE_DEF                   (1 << 22)  #       define R500_TCL_STATE_OPTIMIZATION              (1 << 23) -#define R300_VAP_VTE_CNTL				0x20B0 -#       define R300_VPORT_X_SCALE_ENA                   (1 << 0) -#       define R300_VPORT_X_OFFSET_ENA                  (1 << 1) -#       define R300_VPORT_Y_SCALE_ENA                   (1 << 2) -#       define R300_VPORT_Y_OFFSET_ENA                  (1 << 3) -#       define R300_VPORT_Z_SCALE_ENA                   (1 << 4) -#       define R300_VPORT_Z_OFFSET_ENA                  (1 << 5) -#       define R300_VTX_XY_FMT                          (1 << 8) -#       define R300_VTX_Z_FMT                           (1 << 9) -#       define R300_VTX_W0_FMT                          (1 << 10) -#define R300_VAP_VTX_STATE_CNTL		                0x2180  #define R300_VAP_PSC_SGN_NORM_CNTL		        0x21DC  #define R300_VAP_PROG_STREAM_CNTL_0		        0x2150  #       define R300_DATA_TYPE_0_SHIFT                   0 @@ -4431,8 +4419,6 @@  #       define R300_ENDIAN_SWAP_HALF_DWORD              (3 << 0)  #       define R300_MACRO_TILE                          (1 << 2) -#define R300_TX_BORDER_COLOR_0			        0x45c0 -  #define R300_TX_ENABLE				        0x4104  #       define R300_TEX_0_ENABLE                        (1 << 0)  #       define R300_TEX_1_ENABLE                        (1 << 1) @@ -4719,24 +4705,7 @@  #       define R300_READ_ENABLE                         (1 << 2)  #define R300_RB3D_ABLENDCNTL			        0x4e08  #define R300_RB3D_DSTCACHE_CTLSTAT		        0x4e4c -#define R300_RB3D_COLOROFFSET0			        0x4e28 -#define R300_RB3D_COLORPITCH0			        0x4e38 -#       define R300_COLORTILE                           (1 << 16) -#       define R300_COLORENDIAN_WORD                    (1 << 19) -#       define R300_COLORENDIAN_DWORD                   (2 << 19) -#       define R300_COLORENDIAN_HALF_DWORD              (3 << 19) -#       define R300_COLORFORMAT_ARGB1555                (3 << 21) -#       define R300_COLORFORMAT_RGB565                  (4 << 21) -#       define R300_COLORFORMAT_ARGB8888                (6 << 21) -#       define R300_COLORFORMAT_ARGB32323232            (7 << 21) -#       define R300_COLORFORMAT_I8                      (9 << 21) -#       define R300_COLORFORMAT_ARGB16161616            (10 << 21) -#       define R300_COLORFORMAT_VYUY                    (11 << 21) -#       define R300_COLORFORMAT_YVYU                    (12 << 21) -#       define R300_COLORFORMAT_UV88                    (13 << 21) -#       define R300_COLORFORMAT_ARGB4444                (15 << 21) - -#define R300_RB3D_AARESOLVE_CTL			        0x4e88 +  #define R300_RB3D_COLOR_CHANNEL_MASK	                0x4e0c  #       define R300_BLUE_MASK_EN                        (1 << 0)  #       define R300_GREEN_MASK_EN                       (1 << 1) diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index b31ac2d4..423208b0 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -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;  } diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index f8ed7de8..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, @@ -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 */ | 
