diff options
Diffstat (limited to 'drivers/gpu/drm/mga/mga_irq.c')
| -rw-r--r-- | drivers/gpu/drm/mga/mga_irq.c | 74 | 
1 files changed, 53 insertions, 21 deletions
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index 9302cb8f0f8..bab42f41188 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -1,5 +1,6 @@  /* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- - * + */ +/*   * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.   *   * The Weather Channel (TM) funded Tungsten Graphics to develop the @@ -35,6 +36,18 @@  #include "mga_drm.h"  #include "mga_drv.h" +u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) +{ +	const drm_mga_private_t *const dev_priv = +		(drm_mga_private_t *) dev->dev_private; + +	if (crtc != 0) +		return 0; + +	return atomic_read(&dev_priv->vbl_received); +} + +  irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg; @@ -47,9 +60,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)  	/* VBLANK interrupt */  	if (status & MGA_VLINEPEN) {  		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); -		atomic_inc(&dev->vbl_received); -		DRM_WAKEUP(&dev->vbl_queue); -		drm_vbl_send_signals(dev); +		atomic_inc(&dev_priv->vbl_received); +		drm_handle_vblank(dev, 0);  		handled = 1;  	} @@ -58,6 +70,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)  		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);  		const u32 prim_end = MGA_READ(MGA_PRIMEND); +  		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);  		/* In addition to clearing the interrupt-pending bit, we @@ -72,28 +85,39 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)  		handled = 1;  	} -	if (handled) { +	if (handled)  		return IRQ_HANDLED; -	}  	return IRQ_NONE;  } -int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int mga_enable_vblank(struct drm_device *dev, int crtc)  { -	unsigned int cur_vblank; -	int ret = 0; +	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; -	/* Assume that the user has missed the current sequence number -	 * by about a day rather than she wants to wait for years -	 * using vertical blanks... -	 */ -	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, -		    (((cur_vblank = atomic_read(&dev->vbl_received)) -		      - *sequence) <= (1 << 23))); +	if (crtc != 0) { +		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", +			  crtc); +		return 0; +	} -	*sequence = cur_vblank; +	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); +	return 0; +} -	return ret; + +void mga_disable_vblank(struct drm_device *dev, int crtc) +{ +	if (crtc != 0) { +		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", +			  crtc); +	} + +	/* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have +	 * a nice hardware counter that tracks the number of refreshes when +	 * the interrupt is disabled, and the kernel doesn't know the refresh +	 * rate to calculate an estimate. +	 */ +	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */  }  int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) @@ -125,14 +149,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)  	MGA_WRITE(MGA_ICLEAR, ~0);  } -void mga_driver_irq_postinstall(struct drm_device * dev) +int mga_driver_irq_postinstall(struct drm_device *dev)  {  	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; +	int ret; + +	ret = drm_vblank_init(dev, 1); +	if (ret) +		return ret;  	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); -	/* Turn on vertical blank interrupt and soft trap interrupt. */ -	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); +	/* Turn on soft trap interrupt.  Vertical blank interrupts are enabled +	 * in mga_enable_vblank. +	 */ +	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); +	return 0;  }  void mga_driver_irq_uninstall(struct drm_device * dev)  | 
