Commit 860da5e5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: save and restore dsparb and d_state registers.
  drm/i915: fix off by one in VGA save/restore of AR & CR regs.
  drm: disable tasklets not IRQs when taking the drm lock spinlock
  Revert "drm/vbl rework: rework how the drm deals with vblank."
parents 1bf99477 e948e994
...@@ -471,7 +471,6 @@ struct drm_irq_busid { ...@@ -471,7 +471,6 @@ struct drm_irq_busid {
enum drm_vblank_seq_type { enum drm_vblank_seq_type {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
_DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
_DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
_DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
...@@ -504,21 +503,6 @@ union drm_wait_vblank { ...@@ -504,21 +503,6 @@ union drm_wait_vblank {
struct drm_wait_vblank_reply reply; struct drm_wait_vblank_reply reply;
}; };
enum drm_modeset_ctl_cmd {
_DRM_PRE_MODESET = 1,
_DRM_POST_MODESET = 2,
};
/**
* DRM_IOCTL_MODESET_CTL ioctl argument type
*
* \sa drmModesetCtl().
*/
struct drm_modeset_ctl {
unsigned long arg;
enum drm_modeset_ctl_cmd cmd;
};
/** /**
* DRM_IOCTL_AGP_ENABLE ioctl argument type. * DRM_IOCTL_AGP_ENABLE ioctl argument type.
* *
...@@ -603,7 +587,6 @@ struct drm_set_version { ...@@ -603,7 +587,6 @@ struct drm_set_version {
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
......
...@@ -100,8 +100,10 @@ struct drm_device; ...@@ -100,8 +100,10 @@ struct drm_device;
#define DRIVER_HAVE_DMA 0x20 #define DRIVER_HAVE_DMA 0x20
#define DRIVER_HAVE_IRQ 0x40 #define DRIVER_HAVE_IRQ 0x40
#define DRIVER_IRQ_SHARED 0x80 #define DRIVER_IRQ_SHARED 0x80
#define DRIVER_IRQ_VBL 0x100
#define DRIVER_DMA_QUEUE 0x200 #define DRIVER_DMA_QUEUE 0x200
#define DRIVER_FB_DMA 0x400 #define DRIVER_FB_DMA 0x400
#define DRIVER_IRQ_VBL2 0x800
/***********************************************************************/ /***********************************************************************/
/** \name Begin the DRM... */ /** \name Begin the DRM... */
...@@ -577,52 +579,10 @@ struct drm_driver { ...@@ -577,52 +579,10 @@ struct drm_driver {
int (*context_dtor) (struct drm_device *dev, int context); int (*context_dtor) (struct drm_device *dev, int context);
int (*kernel_context_switch) (struct drm_device *dev, int old, int (*kernel_context_switch) (struct drm_device *dev, int old,
int new); int new);
void (*kernel_context_switch_unlock) (struct drm_device * dev); void (*kernel_context_switch_unlock) (struct drm_device *dev);
/** int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
* get_vblank_counter - get raw hardware vblank counter int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
* @dev: DRM device int (*dri_library_name) (struct drm_device *dev, char *buf);
* @crtc: counter to fetch
*
* Driver callback for fetching a raw hardware vblank counter
* for @crtc. If a device doesn't have a hardware counter, the
* driver can simply return the value of drm_vblank_count and
* make the enable_vblank() and disable_vblank() hooks into no-ops,
* leaving interrupts enabled at all times.
*
* Wraparound handling and loss of events due to modesetting is dealt
* with in the DRM core code.
*
* RETURNS
* Raw vblank counter value.
*/
u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
/**
* enable_vblank - enable vblank interrupt events
* @dev: DRM device
* @crtc: which irq to enable
*
* Enable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate.
*
* RETURNS
* Zero on success, appropriate errno if the given @crtc's vblank
* interrupt cannot be enabled.
*/
int (*enable_vblank) (struct drm_device *dev, int crtc);
/**
* disable_vblank - disable vblank interrupt events
* @dev: DRM device
* @crtc: which irq to enable
*
* Disable vblank interrupts for @crtc. If the device doesn't have
* a hardware vblank counter, this routine should be a no-op, since
* interrupts will have to stay on to keep the count accurate.
*/
void (*disable_vblank) (struct drm_device *dev, int crtc);
int (*dri_library_name) (struct drm_device *dev, char * buf);
/** /**
* Called by \c drm_device_is_agp. Typically used to determine if a * Called by \c drm_device_is_agp. Typically used to determine if a
...@@ -641,7 +601,7 @@ struct drm_driver { ...@@ -641,7 +601,7 @@ struct drm_driver {
irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
void (*irq_preinstall) (struct drm_device *dev); void (*irq_preinstall) (struct drm_device *dev);
int (*irq_postinstall) (struct drm_device *dev); void (*irq_postinstall) (struct drm_device *dev);
void (*irq_uninstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev);
void (*reclaim_buffers) (struct drm_device *dev, void (*reclaim_buffers) (struct drm_device *dev,
struct drm_file * file_priv); struct drm_file * file_priv);
...@@ -770,21 +730,13 @@ struct drm_device { ...@@ -770,21 +730,13 @@ struct drm_device {
/** \name VBLANK IRQ support */ /** \name VBLANK IRQ support */
/*@{ */ /*@{ */
wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ 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) */ atomic_t vbl_received;
atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
spinlock_t vbl_lock; spinlock_t vbl_lock;
struct list_head *vbl_sigs; /**< signal list to send on VBLANK */ struct list_head vbl_sigs; /**< signal list to send on VBLANK */
atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/ struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */ unsigned int vbl_pending;
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 */
struct timer_list vblank_disable_timer;
unsigned long max_vblank_count; /**< size of vblank counter register */
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
void (*locked_tasklet_func)(struct drm_device *dev); void (*locked_tasklet_func)(struct drm_device *dev);
...@@ -804,7 +756,6 @@ struct drm_device { ...@@ -804,7 +756,6 @@ struct drm_device {
#ifdef __alpha__ #ifdef __alpha__
struct pci_controller *hose; struct pci_controller *hose;
#endif #endif
int num_crtcs; /**< Number of CRTCs on this device */
struct drm_sg_mem *sg; /**< Scatter gather memory */ struct drm_sg_mem *sg; /**< Scatter gather memory */
void *dev_private; /**< device private data */ void *dev_private; /**< device private data */
struct drm_sigdata sigdata; /**< For block_all_signals */ struct drm_sigdata sigdata; /**< For block_all_signals */
...@@ -1039,19 +990,11 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev); ...@@ -1039,19 +990,11 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
extern void drm_driver_irq_postinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev);
extern void drm_driver_irq_uninstall(struct drm_device *dev); extern void drm_driver_irq_uninstall(struct drm_device *dev);
extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); extern int drm_wait_vblank(struct drm_device *dev, void *data,
extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
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);
/* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
extern void drm_vbl_send_signals(struct drm_device *dev);
extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
/* AGP/GART support (drm_agpsupport.h) */ /* AGP/GART support (drm_agpsupport.h) */
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
......
...@@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp)
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev; struct drm_device *dev = file_priv->minor->dev;
int retcode = 0; int retcode = 0;
unsigned long irqflags;
lock_kernel(); lock_kernel();
...@@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp)
*/ */
do{ do{
spin_lock_irqsave(&dev->lock.spinlock, spin_lock_bh(&dev->lock.spinlock);
irqflags);
locked = dev->lock.idle_has_lock; locked = dev->lock.idle_has_lock;
spin_unlock_irqrestore(&dev->lock.spinlock, spin_unlock_bh(&dev->lock.spinlock);
irqflags);
if (locked) if (locked)
break; break;
schedule(); schedule();
......
This diff is collapsed.
...@@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
DECLARE_WAITQUEUE(entry, current); DECLARE_WAITQUEUE(entry, current);
struct drm_lock *lock = data; struct drm_lock *lock = data;
int ret = 0; int ret = 0;
unsigned long irqflags;
++file_priv->lock_count; ++file_priv->lock_count;
...@@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL; return -EINVAL;
add_wait_queue(&dev->lock.lock_queue, &entry); add_wait_queue(&dev->lock.lock_queue, &entry);
spin_lock_irqsave(&dev->lock.spinlock, irqflags); spin_lock_bh(&dev->lock.spinlock);
dev->lock.user_waiters++; dev->lock.user_waiters++;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); spin_unlock_bh(&dev->lock.spinlock);
for (;;) { for (;;) {
__set_current_state(TASK_INTERRUPTIBLE); __set_current_state(TASK_INTERRUPTIBLE);
if (!dev->lock.hw_lock) { if (!dev->lock.hw_lock) {
...@@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
break; break;
} }
} }
spin_lock_irqsave(&dev->lock.spinlock, irqflags); spin_lock_bh(&dev->lock.spinlock);
dev->lock.user_waiters--; dev->lock.user_waiters--;
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); spin_unlock_bh(&dev->lock.spinlock);
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry); remove_wait_queue(&dev->lock.lock_queue, &entry);
...@@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data, ...@@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,
{ {
unsigned int old, new, prev; unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
do { do {
old = *lock; old = *lock;
if (old & _DRM_LOCK_HELD) if (old & _DRM_LOCK_HELD)
...@@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data, ...@@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
} }
prev = cmpxchg(lock, old, new); prev = cmpxchg(lock, old, new);
} while (prev != old); } while (prev != old);
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
if (_DRM_LOCKING_CONTEXT(old) == context) { if (_DRM_LOCKING_CONTEXT(old) == context) {
if (old & _DRM_LOCK_HELD) { if (old & _DRM_LOCK_HELD) {
...@@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) ...@@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{ {
unsigned int old, new, prev; unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (lock_data->kernel_waiters != 0) { if (lock_data->kernel_waiters != 0) {
drm_lock_transfer(lock_data, 0); drm_lock_transfer(lock_data, 0);
lock_data->idle_has_lock = 1; lock_data->idle_has_lock = 1;
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
return 1; return 1;
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
do { do {
old = *lock; old = *lock;
...@@ -347,20 +344,19 @@ static int drm_notifier(void *priv) ...@@ -347,20 +344,19 @@ static int drm_notifier(void *priv)
void drm_idlelock_take(struct drm_lock_data *lock_data) void drm_idlelock_take(struct drm_lock_data *lock_data)
{ {
int ret = 0; int ret = 0;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
lock_data->kernel_waiters++; lock_data->kernel_waiters++;
if (!lock_data->idle_has_lock) { if (!lock_data->idle_has_lock) {
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (ret == 1) if (ret == 1)
lock_data->idle_has_lock = 1; lock_data->idle_has_lock = 1;
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
} }
EXPORT_SYMBOL(drm_idlelock_take); EXPORT_SYMBOL(drm_idlelock_take);
...@@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) ...@@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
{ {
unsigned int old, prev; unsigned int old, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock; volatile unsigned int *lock = &lock_data->hw_lock->lock;
unsigned long irqflags;
spin_lock_irqsave(&lock_data->spinlock, irqflags); spin_lock_bh(&lock_data->spinlock);
if (--lock_data->kernel_waiters == 0) { if (--lock_data->kernel_waiters == 0) {
if (lock_data->idle_has_lock) { if (lock_data->idle_has_lock) {
do { do {
...@@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) ...@@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
lock_data->idle_has_lock = 0; lock_data->idle_has_lock = 0;
} }
} }
spin_unlock_irqrestore(&lock_data->spinlock, irqflags); spin_unlock_bh(&lock_data->spinlock);
} }
EXPORT_SYMBOL(drm_idlelock_release); EXPORT_SYMBOL(drm_idlelock_release);
......
...@@ -415,13 +415,10 @@ static void i915_emit_breadcrumb(struct drm_device *dev) ...@@ -415,13 +415,10 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS; RING_LOCALS;
if (++dev_priv->counter > BREADCRUMB_MASK) { dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
dev_priv->counter = 1;
DRM_DEBUG("Breadcrumb counter wrapped around\n");
}
if (dev_priv->sarea_priv) if (dev_priv->counter > 0x7FFFFFFFUL)
dev_priv->sarea_priv->last_enqueue = dev_priv->counter; dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
BEGIN_LP_RING(4); BEGIN_LP_RING(4);
OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(CMD_STORE_DWORD_IDX);
...@@ -431,26 +428,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev) ...@@ -431,26 +428,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
ADVANCE_LP_RING(); ADVANCE_LP_RING();
} }
int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
{
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t flush_cmd = CMD_MI_FLUSH;
RING_LOCALS;
flush_cmd |= flush;
i915_kernel_lost_context(dev);
BEGIN_LP_RING(4);
OUT_RING(flush_cmd);
OUT_RING(0);
OUT_RING(0);
OUT_RING(0);
ADVANCE_LP_RING();
return 0;
}
static int i915_dispatch_cmdbuffer(struct drm_device * dev, static int i915_dispatch_cmdbuffer(struct drm_device * dev,
drm_i915_cmdbuffer_t * cmd) drm_i915_cmdbuffer_t * cmd)
{ {
...@@ -534,74 +511,52 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, ...@@ -534,74 +511,52 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
return 0; return 0;
} }
static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) static int i915_dispatch_flip(struct drm_device * dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 num_pages, current_page, next_page, dspbase;
int shift = 2 * plane, x, y;
RING_LOCALS; RING_LOCALS;
/* Calculate display base offset */ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; __FUNCTION__,
current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3; dev_priv->current_page,
next_page = (current_page + 1) % num_pages; dev_priv->sarea_priv->pf_current_page);
switch (next_page) { i915_kernel_lost_context(dev);
default:
case 0: BEGIN_LP_RING(2);
dspbase = dev_priv->sarea_priv->front_offset; OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
break; OUT_RING(0);
case 1: ADVANCE_LP_RING();
dspbase = dev_priv->sarea_priv->back_offset;
break;
case 2:
dspbase = dev_priv->sarea_priv->third_offset;
break;
}
if (plane == 0) { BEGIN_LP_RING(6);
x = dev_priv->sarea_priv->planeA_x; OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
y = dev_priv->sarea_priv->planeA_y; OUT_RING(0);
if (dev_priv->current_page == 0) {
OUT_RING(dev_priv->back_offset);
dev_priv->current_page = 1;
} else { } else {
x = dev_priv->sarea_priv->planeB_x; OUT_RING(dev_priv->front_offset);
y = dev_priv->sarea_priv->planeB_y; dev_priv->current_page = 0;
} }
OUT_RING(0);
ADVANCE_LP_RING();
dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp; BEGIN_LP_RING(2);
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
OUT_RING(0);
ADVANCE_LP_RING();
DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page, dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
dspbase);
BEGIN_LP_RING(4); BEGIN_LP_RING(4);
OUT_RING(sync ? 0 : OUT_RING(CMD_STORE_DWORD_IDX);
(MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP : OUT_RING(20);
MI_WAIT_FOR_PLANE_A_FLIP))); OUT_RING(dev_priv->counter);
OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) | OUT_RING(0);
(plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
OUT_RING(dspbase);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift); dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
dev_priv->sarea_priv->pf_current_page |= next_page << shift; return 0;
}
void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
planes, dev_priv->sarea_priv->pf_current_page);
i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
for (i = 0; i < 2; i++)
if (planes & (1 << i))
i915_do_dispatch_flip(dev, i, sync);
i915_emit_breadcrumb(dev);
} }
static int i915_quiescent(struct drm_device * dev) static int i915_quiescent(struct drm_device * dev)
...@@ -624,6 +579,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ...@@ -624,6 +579,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
dev_priv->sarea_priv; dev_priv->sarea_priv;
drm_i915_batchbuffer_t *batch = data; drm_i915_batchbuffer_t *batch = data;
...@@ -646,7 +602,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ...@@ -646,7 +602,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
ret = i915_dispatch_batchbuffer(dev, batch); ret = i915_dispatch_batchbuffer(dev, batch);
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); sarea_priv->last_dispatch = (int)hw_status[5];
return ret; return ret;
} }
...@@ -654,6 +610,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -654,6 +610,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
dev_priv->sarea_priv; dev_priv->sarea_priv;
drm_i915_cmdbuffer_t *cmdbuf = data; drm_i915_cmdbuffer_t *cmdbuf = data;
...@@ -678,51 +635,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -678,51 +635,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
return ret; return ret;
} }
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); sarea_priv->last_dispatch = (int)hw_status[5];
return 0;
}
static int i915_do_cleanup_pageflip(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
DRM_DEBUG("\n");
for (i = 0, planes = 0; i < 2; i++)
if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
dev_priv->sarea_priv->pf_current_page =
(dev_priv->sarea_priv->pf_current_page &
~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
planes |= 1 << i;
}
if (planes)
i915_dispatch_flip(dev, planes, 0);
return 0; return 0;
} }
static int i915_flip_bufs(struct drm_device *dev, void *data, static int i915_flip_bufs(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
drm_i915_flip_t *param = data; DRM_DEBUG("%s\n", __FUNCTION__);
DRM_DEBUG("\n");
LOCK_TEST_WITH_RETURN(dev, file_priv); LOCK_TEST_WITH_RETURN(dev, file_priv);
/* This is really planes */ return i915_dispatch_flip(dev);
if (param->pipes & ~0x3) {
DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
param->pipes);
return -EINVAL;
}
i915_dispatch_flip(dev, param->pipes, 0);
return 0;
} }
static int i915_getparam(struct drm_device *dev, void *data, static int i915_getparam(struct drm_device *dev, void *data,
...@@ -883,8 +807,6 @@ void i915_driver_lastclose(struct drm_device * dev) ...@@ -883,8 +807,6 @@ void i915_driver_lastclose(struct drm_device * dev)
if (!dev_priv) if (!dev_priv)
return; return;
if (drm_getsarea(dev) && dev_priv->sarea_priv)
i915_do_cleanup_pageflip(dev);
if (dev_priv->agp_heap) if (dev_priv->agp_heap)
i915_mem_takedown(&(dev_priv->agp_heap)); i915_mem_takedown(&(dev_priv->agp_heap));
......
...@@ -105,29 +105,14 @@ typedef struct _drm_i915_sarea { ...@@ -105,29 +105,14 @@ typedef struct _drm_i915_sarea {
unsigned int rotated_tiled; unsigned int rotated_tiled;
unsigned int rotated2_tiled; unsigned int rotated2_tiled;
int planeA_x; int pipeA_x;
int planeA_y; int pipeA_y;
int planeA_w; int pipeA_w;
int planeA_h; int pipeA_h;
int planeB_x; int pipeB_x;
int planeB_y; int pipeB_y;
int planeB_w; int pipeB_w;
int planeB_h; int pipeB_h;
/* Triple buffering */
drm_handle_t third_handle;
int third_offset;
int third_size;
unsigned int third_tiled;
/* buffer object handles for the static buffers. May change
* over the lifetime of the client, though it doesn't in our current
* implementation.
*/
unsigned int front_bo_handle;
unsigned int back_bo_handle;
unsigned int third_bo_handle;
unsigned int depth_bo_handle;
} drm_i915_sarea_t; } drm_i915_sarea_t;
/* Flags for perf_boxes /* Flags for perf_boxes
...@@ -161,7 +146,7 @@ typedef struct _drm_i915_sarea { ...@@ -161,7 +146,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
#define DRM_IOCTL_I915_FLIP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t) #define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) #define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) #define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) #define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
...@@ -176,18 +161,6 @@ typedef struct _drm_i915_sarea { ...@@ -176,18 +161,6 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
/* Asynchronous page flipping:
*/
typedef struct drm_i915_flip {
/*
* This is really talking about planes, and we could rename it
* except for the fact that some of the duplicated i915_drm.h files
* out there check for HAVE_I915_FLIP and so might pick up this
* version.
*/
int pipes;
} drm_i915_flip_t;
/* Allow drivers to submit batchbuffers directly to hardware, relying /* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware. * on the security mechanisms provided by hardware.
*/ */
......
...@@ -147,7 +147,7 @@ static void i915_save_vga(struct drm_device *dev) ...@@ -147,7 +147,7 @@ static void i915_save_vga(struct drm_device *dev)
i915_write_indexed(cr_index, cr_data, 0x11, i915_write_indexed(cr_index, cr_data, 0x11,
i915_read_indexed(cr_index, cr_data, 0x11) & i915_read_indexed(cr_index, cr_data, 0x11) &
(~0x80)); (~0x80));
for (i = 0; i < 0x24; i++) for (i = 0; i <= 0x24; i++)
dev_priv->saveCR[i] = dev_priv->saveCR[i] =
i915_read_indexed(cr_index, cr_data, i); i915_read_indexed(cr_index, cr_data, i);
/* Make sure we don't turn off CR group 0 writes */ /* Make sure we don't turn off CR group 0 writes */
...@@ -156,7 +156,7 @@ static void i915_save_vga(struct drm_device *dev) ...@@ -156,7 +156,7 @@ static void i915_save_vga(struct drm_device *dev)
/* Attribute controller registers */ /* Attribute controller registers */
inb(st01); inb(st01);
dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX); dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
for (i = 0; i < 20; i++) for (i = 0; i <= 0x14; i++)
dev_priv->saveAR[i] = i915_read_ar(st01, i, 0); dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
inb(st01); inb(st01);
outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX); outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
...@@ -206,7 +206,7 @@ static void i915_restore_vga(struct drm_device *dev) ...@@ -206,7 +206,7 @@ static void i915_restore_vga(struct drm_device *dev)
/* CRT controller regs */ /* CRT controller regs */
/* Enable CR group 0 writes */ /* Enable CR group 0 writes */
i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]); i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
for (i = 0; i < 0x24; i++) for (i = 0; i <= 0x24; i++)
i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]); i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
/* Graphics controller regs */ /* Graphics controller regs */
...@@ -223,7 +223,7 @@ static void i915_restore_vga(struct drm_device *dev) ...@@ -223,7 +223,7 @@ static void i915_restore_vga(struct drm_device *dev)
/* Attribute controller registers */ /* Attribute controller registers */
inb(st01); inb(st01);
for (i = 0; i < 20; i++) for (i = 0; i <= 0x14; i++)
i915_write_ar(st01, i, dev_priv->saveAR[i], 0); i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
inb(st01); /* switch back to index mode */ inb(st01); /* switch back to index mode */
outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX); outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
...@@ -256,6 +256,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) ...@@ -256,6 +256,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
pci_save_state(dev->pdev); pci_save_state(dev->pdev);
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
/* Display arbitration control */
dev_priv->saveDSPARB = I915_READ(DSPARB);
/* Pipe & plane A info */ /* Pipe & plane A info */
dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
dev_priv->savePIPEASRC = I915_READ(PIPEASRC); dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
...@@ -349,6 +352,7 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) ...@@ -349,6 +352,7 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
/* Clock gating state */ /* Clock gating state */
dev_priv->saveD_STATE = I915_READ(D_STATE);
dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
/* Cache mode state */ /* Cache mode state */
...@@ -388,6 +392,8 @@ static int i915_resume(struct drm_device *dev) ...@@ -388,6 +392,8 @@ static int i915_resume(struct drm_device *dev)
pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
/* Pipe & plane A info */ /* Pipe & plane A info */
/* Prime the clock */ /* Prime the clock */
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
...@@ -507,6 +513,7 @@ static int i915_resume(struct drm_device *dev) ...@@ -507,6 +513,7 @@ static int i915_resume(struct drm_device *dev)
udelay(150); udelay(150);
/* Clock gating state */ /* Clock gating state */
I915_WRITE (D_STATE, dev_priv->saveD_STATE);
I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D); I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
/* Cache mode state */ /* Cache mode state */
...@@ -533,7 +540,8 @@ static struct drm_driver driver = { ...@@ -533,7 +540,8 @@ static struct drm_driver driver = {
*/ */
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
DRIVER_IRQ_VBL2,
.load = i915_driver_load, .load = i915_driver_load,
.unload = i915_driver_unload, .unload = i915_driver_unload,
.lastclose = i915_driver_lastclose, .lastclose = i915_driver_lastclose,
...@@ -541,9 +549,8 @@ static struct drm_driver driver = { ...@@ -541,9 +549,8 @@ static struct drm_driver driver = {
.suspend = i915_suspend, .suspend = i915_suspend,
.resume = i915_resume, .resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp, .device_is_agp = i915_driver_device_is_agp,
.get_vblank_counter = i915_get_vblank_counter, .vblank_wait = i915_driver_vblank_wait,
.enable_vblank = i915_enable_vblank, .vblank_wait2 = i915_driver_vblank_wait2,
.disable_vblank = i915_disable_vblank,
.irq_preinstall = i915_driver_irq_preinstall, .irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall, .irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall, .irq_uninstall = i915_driver_irq_uninstall,
......
...@@ -76,9 +76,8 @@ struct mem_block { ...@@ -76,9 +76,8 @@ struct mem_block {
typedef struct _drm_i915_vbl_swap { typedef struct _drm_i915_vbl_swap {
struct list_head head; struct list_head head;
drm_drawable_t drw_id; drm_drawable_t drw_id;
unsigned int plane; unsigned int pipe;
unsigned int sequence; unsigned int sequence;
int flip;
} drm_i915_vbl_swap_t; } drm_i915_vbl_swap_t;
typedef struct drm_i915_private { typedef struct drm_i915_private {
...@@ -91,7 +90,7 @@ typedef struct drm_i915_private { ...@@ -91,7 +90,7 @@ typedef struct drm_i915_private {
drm_dma_handle_t *status_page_dmah; drm_dma_handle_t *status_page_dmah;
void *hw_status_page; void *hw_status_page;
dma_addr_t dma_status_page; dma_addr_t dma_status_page;
uint32_t counter; unsigned long counter;
unsigned int status_gfx_addr; unsigned int status_gfx_addr;
drm_local_map_t hws_map; drm_local_map_t hws_map;
...@@ -104,18 +103,13 @@ typedef struct drm_i915_private { ...@@ -104,18 +103,13 @@ typedef struct drm_i915_private {
wait_queue_head_t irq_queue; wait_queue_head_t irq_queue;
atomic_t irq_received; atomic_t irq_received;
atomic_t irq_emited; atomic_t irq_emitted;
int tex_lru_log_granularity; int tex_lru_log_granularity;
int allow_batchbuffer; int allow_batchbuffer;
struct mem_block *agp_heap; struct mem_block *agp_heap;
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe; int vblank_pipe;
spinlock_t user_irq_lock;
int user_irq_refcount;
int fence_irq_on;
uint32_t irq_enable_reg;
int irq_enabled;
spinlock_t swaps_lock; spinlock_t swaps_lock;
drm_i915_vbl_swap_t vbl_swaps; drm_i915_vbl_swap_t vbl_swaps;
...@@ -125,6 +119,7 @@ typedef struct drm_i915_private { ...@@ -125,6 +119,7 @@ typedef struct drm_i915_private {
u8 saveLBB; u8 saveLBB;
u32 saveDSPACNTR; u32 saveDSPACNTR;
u32 saveDSPBCNTR; u32 saveDSPBCNTR;
u32 saveDSPARB;
u32 savePIPEACONF; u32 savePIPEACONF;
u32 savePIPEBCONF; u32 savePIPEBCONF;
u32 savePIPEASRC; u32 savePIPEASRC;
...@@ -194,6 +189,7 @@ typedef struct drm_i915_private { ...@@ -194,6 +189,7 @@ typedef struct drm_i915_private {
u32 saveIIR; u32 saveIIR;
u32 saveIMR; u32 saveIMR;
u32 saveCACHE_MODE_0; u32 saveCACHE_MODE_0;
u32 saveD_STATE;
u32 saveDSPCLK_GATE_D; u32 saveDSPCLK_GATE_D;
u32 saveMI_ARB_STATE; u32 saveMI_ARB_STATE;
u32 saveSWF0[16]; u32 saveSWF0[16];
...@@ -203,10 +199,10 @@ typedef struct drm_i915_private { ...@@ -203,10 +199,10 @@ typedef struct drm_i915_private {
u8 saveSR[8]; u8 saveSR[8];
u8 saveGR[25]; u8 saveGR[25];
u8 saveAR_INDEX; u8 saveAR_INDEX;
u8 saveAR[20]; u8 saveAR[21];
u8 saveDACMASK; u8 saveDACMASK;
u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveDACDATA[256*3]; /* 256 3-byte colors */
u8 saveCR[36]; u8 saveCR[37];
} drm_i915_private_t; } drm_i915_private_t;
extern struct drm_ioctl_desc i915_ioctls[]; extern struct drm_ioctl_desc i915_ioctls[];
...@@ -222,7 +218,7 @@ extern void i915_driver_preclose(struct drm_device *dev, ...@@ -222,7 +218,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
extern int i915_driver_device_is_agp(struct drm_device * dev); extern int i915_driver_device_is_agp(struct drm_device * dev);
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg); unsigned long arg);
extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
/* i915_irq.c */ /* i915_irq.c */
extern int i915_irq_emit(struct drm_device *dev, void *data, extern int i915_irq_emit(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
...@@ -233,7 +229,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc ...@@ -233,7 +229,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(struct drm_device * dev); extern void i915_driver_irq_preinstall(struct drm_device * dev);
extern int i915_driver_irq_postinstall(struct drm_device * dev); extern void i915_driver_irq_postinstall(struct drm_device * dev);
extern void i915_driver_irq_uninstall(struct drm_device * dev); extern void i915_driver_irq_uninstall(struct drm_device * dev);
extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
...@@ -241,9 +237,6 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, ...@@ -241,9 +237,6 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int i915_vblank_swap(struct drm_device *dev, void *data, extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
/* i915_mem.c */ /* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data, extern int i915_mem_alloc(struct drm_device *dev, void *data,
...@@ -388,91 +381,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -388,91 +381,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/* Interrupt bits: /* Interrupt bits:
*/ */
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) #define USER_INT_FLAG (1<<1)
#define I915_DISPLAY_PORT_INTERRUPT (1<<17) #define VSYNC_PIPEB_FLAG (1<<5)
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) #define VSYNC_PIPEA_FLAG (1<<7)
#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) #define HWB_OOM_FLAG (1<<13) /* binner out of memory */
#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */
#define I915_SYNC_STATUS_INTERRUPT (1<<12)
#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9)
#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7)
#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6)
#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5)
#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
#define I915_DEBUG_INTERRUPT (1<<2)
#define I915_USER_INTERRUPT (1<<1)
#define I915REG_HWSTAM 0x02098 #define I915REG_HWSTAM 0x02098
#define I915REG_INT_IDENTITY_R 0x020a4 #define I915REG_INT_IDENTITY_R 0x020a4
#define I915REG_INT_MASK_R 0x020a8 #define I915REG_INT_MASK_R 0x020a8
#define I915REG_INT_ENABLE_R 0x020a0 #define I915REG_INT_ENABLE_R 0x020a0
#define I915REG_INSTPM 0x020c0
#define PIPEADSL 0x70000
#define PIPEBDSL 0x71000
#define I915REG_PIPEASTAT 0x70024 #define I915REG_PIPEASTAT 0x70024
#define I915REG_PIPEBSTAT 0x71024 #define I915REG_PIPEBSTAT 0x71024
/*
* The two pipe frame counter registers are not synchronized, so
* reading a stable value is somewhat tricky. The following code
* should work:
*
* do {
* high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
* PIPE_FRAME_HIGH_SHIFT;
* low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
* PIPE_FRAME_LOW_SHIFT);
* high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
* PIPE_FRAME_HIGH_SHIFT);
* } while (high1 != high2);
* frame = (high1 << 8) | low1;
*/
#define PIPEAFRAMEHIGH 0x70040
#define PIPEBFRAMEHIGH 0x71040
#define PIPE_FRAME_HIGH_MASK 0x0000ffff
#define PIPE_FRAME_HIGH_SHIFT 0
#define PIPEAFRAMEPIXEL 0x70044
#define PIPEBFRAMEPIXEL 0x71044
#define PIPE_FRAME_LOW_MASK 0xff000000
#define PIPE_FRAME_LOW_SHIFT 24
/*
* Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
* and is 24 bits wide.
*/
#define PIPE_PIXEL_MASK 0x00ffffff
#define PIPE_PIXEL_SHIFT 0
#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
#define I915_CRC_ERROR_ENABLE (1UL<<29)
#define I915_CRC_DONE_ENABLE (1UL<<28)
#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
#define I915_DPST_EVENT_ENABLE (1UL<<23)
#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) #define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16) #define I915_VBLANK_CLEAR (1UL<<1)
#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
#define I915_DPST_EVENT_STATUS (1UL<<7)
#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
#define SRX_INDEX 0x3c4 #define SRX_INDEX 0x3c4
#define SRX_DATA 0x3c5 #define SRX_DATA 0x3c5
...@@ -749,6 +672,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -749,6 +672,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/** P1 value is 2 greater than this field */ /** P1 value is 2 greater than this field */
# define VGA0_PD_P1_MASK (0x1f << 0) # define VGA0_PD_P1_MASK (0x1f << 0)
/* PCI D state control register */
#define D_STATE 0x6104
#define DSPCLK_GATE_D 0x6200 #define DSPCLK_GATE_D 0x6200
/* I830 CRTC registers */ /* I830 CRTC registers */
...@@ -1059,6 +984,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -1059,6 +984,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
#define DSPARB 0x70030
#define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_CSTART_SHIFT 7
#define DSPARB_BSTART_MASK (0x7f)
#define DSPARB_BSTART_SHIFT 0
#define PIPEBCONF 0x71008 #define PIPEBCONF 0x71008
#define PIPEBCONF_ENABLE (1<<31) #define PIPEBCONF_ENABLE (1<<31)
#define PIPEBCONF_DISABLE 0 #define PIPEBCONF_DISABLE 0
......
This diff is collapsed.
...@@ -45,16 +45,15 @@ static struct pci_device_id pciidlist[] = { ...@@ -45,16 +45,15 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_mga_buf_priv_t), .dev_priv_size = sizeof(drm_mga_buf_priv_t),
.load = mga_driver_load, .load = mga_driver_load,
.unload = mga_driver_unload, .unload = mga_driver_unload,
.lastclose = mga_driver_lastclose, .lastclose = mga_driver_lastclose,
.dma_quiescent = mga_driver_dma_quiescent, .dma_quiescent = mga_driver_dma_quiescent,
.device_is_agp = mga_driver_device_is_agp, .device_is_agp = mga_driver_device_is_agp,
.get_vblank_counter = mga_get_vblank_counter, .vblank_wait = mga_driver_vblank_wait,
.enable_vblank = mga_enable_vblank,
.disable_vblank = mga_disable_vblank,
.irq_preinstall = mga_driver_irq_preinstall, .irq_preinstall = mga_driver_irq_preinstall,
.irq_postinstall = mga_driver_irq_postinstall, .irq_postinstall = mga_driver_irq_postinstall,
.irq_uninstall = mga_driver_irq_uninstall, .irq_uninstall = mga_driver_irq_uninstall,
......
...@@ -120,7 +120,6 @@ typedef struct drm_mga_private { ...@@ -120,7 +120,6 @@ typedef struct drm_mga_private {
u32 clear_cmd; u32 clear_cmd;
u32 maccess; u32 maccess;
atomic_t vbl_received; /**< Number of vblanks received. */
wait_queue_head_t fence_queue; wait_queue_head_t fence_queue;
atomic_t last_fence_retired; atomic_t last_fence_retired;
u32 next_fence_to_post; u32 next_fence_to_post;
...@@ -182,14 +181,11 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); ...@@ -182,14 +181,11 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
extern int mga_warp_init(drm_mga_private_t * dev_priv); extern int mga_warp_init(drm_mga_private_t * dev_priv);
/* mga_irq.c */ /* mga_irq.c */
extern int mga_enable_vblank(struct drm_device *dev, int crtc);
extern void mga_disable_vblank(struct drm_device *dev, int crtc);
extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence); extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
extern void mga_driver_irq_preinstall(struct drm_device * dev); extern void mga_driver_irq_preinstall(struct drm_device * dev);
extern int mga_driver_irq_postinstall(struct drm_device * dev); extern void mga_driver_irq_postinstall(struct drm_device * dev);
extern void mga_driver_irq_uninstall(struct drm_device * dev); extern void mga_driver_irq_uninstall(struct drm_device * dev);
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg); unsigned long arg);
......
...@@ -35,20 +35,6 @@ ...@@ -35,20 +35,6 @@
#include "mga_drm.h" #include "mga_drm.h"
#include "mga_drv.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) irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -61,8 +47,9 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -61,8 +47,9 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
/* VBLANK interrupt */ /* VBLANK interrupt */
if (status & MGA_VLINEPEN) { if (status & MGA_VLINEPEN) {
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
atomic_inc(&dev_priv->vbl_received); atomic_inc(&dev->vbl_received);
drm_handle_vblank(dev, 0); DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
handled = 1; handled = 1;
} }
...@@ -91,34 +78,22 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -91,34 +78,22 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE; return IRQ_NONE;
} }
int mga_enable_vblank(struct drm_device *dev, int crtc) int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{ {
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; unsigned int cur_vblank;
int ret = 0;
if (crtc != 0) {
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
crtc);
return 0;
}
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
return 0;
}
/* 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)));
void mga_disable_vblank(struct drm_device *dev, int crtc) *sequence = cur_vblank;
{
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 return ret;
* 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) int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
...@@ -150,22 +125,14 @@ void mga_driver_irq_preinstall(struct drm_device * dev) ...@@ -150,22 +125,14 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
MGA_WRITE(MGA_ICLEAR, ~0); MGA_WRITE(MGA_ICLEAR, ~0);
} }
int mga_driver_irq_postinstall(struct drm_device * dev) void mga_driver_irq_postinstall(struct drm_device * dev)
{ {
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 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); DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
/* Turn on soft trap interrupt. Vertical blank interrupts are enabled /* Turn on vertical blank interrupt and soft trap interrupt. */
* in mga_enable_vblank. MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
*/
MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
return 0;
} }
void mga_driver_irq_uninstall(struct drm_device * dev) void mga_driver_irq_uninstall(struct drm_device * dev)
......
...@@ -43,13 +43,12 @@ static struct pci_device_id pciidlist[] = { ...@@ -43,13 +43,12 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_r128_buf_priv_t), .dev_priv_size = sizeof(drm_r128_buf_priv_t),
.preclose = r128_driver_preclose, .preclose = r128_driver_preclose,
.lastclose = r128_driver_lastclose, .lastclose = r128_driver_lastclose,
.get_vblank_counter = r128_get_vblank_counter, .vblank_wait = r128_driver_vblank_wait,
.enable_vblank = r128_enable_vblank,
.disable_vblank = r128_disable_vblank,
.irq_preinstall = r128_driver_irq_preinstall, .irq_preinstall = r128_driver_irq_preinstall,
.irq_postinstall = r128_driver_irq_postinstall, .irq_postinstall = r128_driver_irq_postinstall,
.irq_uninstall = r128_driver_irq_uninstall, .irq_uninstall = r128_driver_irq_uninstall,
......
...@@ -97,8 +97,6 @@ typedef struct drm_r128_private { ...@@ -97,8 +97,6 @@ typedef struct drm_r128_private {
u32 crtc_offset; u32 crtc_offset;
u32 crtc_offset_cntl; u32 crtc_offset_cntl;
atomic_t vbl_received;
u32 color_fmt; u32 color_fmt;
unsigned int front_offset; unsigned int front_offset;
unsigned int front_pitch; unsigned int front_pitch;
...@@ -151,12 +149,11 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n); ...@@ -151,12 +149,11 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv); extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
extern int r128_do_cleanup_cce(struct drm_device * dev); extern int r128_do_cleanup_cce(struct drm_device * dev);
extern int r128_enable_vblank(struct drm_device *dev, int crtc); extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern void r128_disable_vblank(struct drm_device *dev, int crtc);
extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
extern void r128_driver_irq_preinstall(struct drm_device * dev); extern void r128_driver_irq_preinstall(struct drm_device * dev);
extern int r128_driver_irq_postinstall(struct drm_device * dev); extern void r128_driver_irq_postinstall(struct drm_device * dev);
extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev);
extern void r128_driver_lastclose(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev);
extern void r128_driver_preclose(struct drm_device * dev, extern void r128_driver_preclose(struct drm_device * dev,
......
...@@ -35,16 +35,6 @@ ...@@ -35,16 +35,6 @@
#include "r128_drm.h" #include "r128_drm.h"
#include "r128_drv.h" #include "r128_drv.h"
u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
{
const drm_r128_private_t *dev_priv = dev->dev_private;
if (crtc != 0)
return 0;
return atomic_read(&dev_priv->vbl_received);
}
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -56,38 +46,30 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -56,38 +46,30 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
/* VBLANK interrupt */ /* VBLANK interrupt */
if (status & R128_CRTC_VBLANK_INT) { if (status & R128_CRTC_VBLANK_INT) {
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
atomic_inc(&dev_priv->vbl_received); atomic_inc(&dev->vbl_received);
drm_handle_vblank(dev, 0); DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
} }
int r128_enable_vblank(struct drm_device *dev, int crtc) int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{ {
drm_r128_private_t *dev_priv = dev->dev_private; unsigned int cur_vblank;
int ret = 0;
if (crtc != 0) {
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
return -EINVAL;
}
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); /* Assume that the user has missed the current sequence number
return 0; * 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)));
void r128_disable_vblank(struct drm_device *dev, int crtc) *sequence = cur_vblank;
{
if (crtc != 0)
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
/* return ret;
* FIXME: implement proper interrupt disable by using the vblank
* counter register (if available)
*
* R128_WRITE(R128_GEN_INT_CNTL,
* R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
*/
} }
void r128_driver_irq_preinstall(struct drm_device * dev) void r128_driver_irq_preinstall(struct drm_device * dev)
...@@ -100,9 +82,12 @@ void r128_driver_irq_preinstall(struct drm_device * dev) ...@@ -100,9 +82,12 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
} }
int r128_driver_irq_postinstall(struct drm_device * dev) void r128_driver_irq_postinstall(struct drm_device * dev)
{ {
return drm_vblank_init(dev, 1); drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
/* Turn on VBL interrupt */
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
} }
void r128_driver_irq_uninstall(struct drm_device * dev) void r128_driver_irq_uninstall(struct drm_device * dev)
......
...@@ -59,7 +59,8 @@ static struct pci_device_id pciidlist[] = { ...@@ -59,7 +59,8 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t), .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load, .load = radeon_driver_load,
.firstopen = radeon_driver_firstopen, .firstopen = radeon_driver_firstopen,
...@@ -68,9 +69,8 @@ static struct drm_driver driver = { ...@@ -68,9 +69,8 @@ static struct drm_driver driver = {
.postclose = radeon_driver_postclose, .postclose = radeon_driver_postclose,
.lastclose = radeon_driver_lastclose, .lastclose = radeon_driver_lastclose,
.unload = radeon_driver_unload, .unload = radeon_driver_unload,
.get_vblank_counter = radeon_get_vblank_counter, .vblank_wait = radeon_driver_vblank_wait,
.enable_vblank = radeon_enable_vblank, .vblank_wait2 = radeon_driver_vblank_wait2,
.disable_vblank = radeon_disable_vblank,
.dri_library_name = dri_library_name, .dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall, .irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall, .irq_postinstall = radeon_driver_irq_postinstall,
......
...@@ -304,9 +304,6 @@ typedef struct drm_radeon_private { ...@@ -304,9 +304,6 @@ typedef struct drm_radeon_private {
u32 scratch_ages[5]; u32 scratch_ages[5];
unsigned int crtc_last_cnt;
unsigned int crtc2_last_cnt;
/* starting from here on, data is preserved accross an open */ /* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */ uint32_t flags; /* see radeon_chip_flags */
unsigned long fb_aper_offset; unsigned long fb_aper_offset;
...@@ -377,13 +374,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file * ...@@ -377,13 +374,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
extern void radeon_do_release(struct drm_device * dev); extern void radeon_do_release(struct drm_device * dev);
extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); extern int radeon_driver_vblank_wait(struct drm_device * dev,
extern int radeon_enable_vblank(struct drm_device *dev, int crtc); unsigned int *sequence);
extern void radeon_disable_vblank(struct drm_device *dev, int crtc); extern int radeon_driver_vblank_wait2(struct drm_device * dev,
extern void radeon_do_release(struct drm_device * dev); unsigned int *sequence);
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(struct drm_device * dev); extern void radeon_driver_irq_preinstall(struct drm_device * dev);
extern int radeon_driver_irq_postinstall(struct drm_device * dev); extern void radeon_driver_irq_postinstall(struct drm_device * dev);
extern void radeon_driver_irq_uninstall(struct drm_device * dev); extern void radeon_driver_irq_uninstall(struct drm_device * dev);
extern int radeon_vblank_crtc_get(struct drm_device *dev); extern int radeon_vblank_crtc_get(struct drm_device *dev);
extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
...@@ -561,12 +558,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, ...@@ -561,12 +558,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
#define RADEON_CRTC_CRNT_FRAME 0x0214
#define RADEON_CRTC2_CRNT_FRAME 0x0314
#define RADEON_CRTC_STATUS 0x005c
#define RADEON_CRTC2_STATUS 0x03fc
#define RADEON_GEN_INT_CNTL 0x0040 #define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_CRTC2_VBLANK_MASK (1 << 9) # define RADEON_CRTC2_VBLANK_MASK (1 << 9)
......
...@@ -35,61 +35,12 @@ ...@@ -35,61 +35,12 @@
#include "radeon_drm.h" #include "radeon_drm.h"
#include "radeon_drv.h" #include "radeon_drv.h"
static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
u32 mask)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
if (state)
dev_priv->irq_enable_reg |= mask;
else
dev_priv->irq_enable_reg &= ~mask;
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
}
int radeon_enable_vblank(struct drm_device *dev, int crtc)
{
switch (crtc) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
break;
case 1:
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
break;
default:
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
crtc);
return EINVAL;
}
return 0;
}
void radeon_disable_vblank(struct drm_device *dev, int crtc)
{
switch (crtc) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
break;
case 1:
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
break;
default:
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
crtc);
break;
}
}
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
{
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
(RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
RADEON_CRTC2_VBLANK_STAT);
if (irqs) if (irqs)
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
return irqs; return irqs;
} }
...@@ -121,21 +72,39 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -121,21 +72,39 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
/* Only consider the bits we're interested in - others could be used /* Only consider the bits we're interested in - others could be used
* outside the DRM * outside the DRM
*/ */
stat = radeon_acknowledge_irqs(dev_priv); stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
RADEON_CRTC_VBLANK_STAT |
RADEON_CRTC2_VBLANK_STAT));
if (!stat) if (!stat)
return IRQ_NONE; return IRQ_NONE;
stat &= dev_priv->irq_enable_reg; stat &= dev_priv->irq_enable_reg;
/* SW interrupt */ /* SW interrupt */
if (stat & RADEON_SW_INT_TEST) if (stat & RADEON_SW_INT_TEST) {
DRM_WAKEUP(&dev_priv->swi_queue); DRM_WAKEUP(&dev_priv->swi_queue);
}
/* VBLANK interrupt */ /* VBLANK interrupt */
if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
int vblank_crtc = dev_priv->vblank_crtc;
if ((vblank_crtc &
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
if (stat & RADEON_CRTC_VBLANK_STAT) if (stat & RADEON_CRTC_VBLANK_STAT)
drm_handle_vblank(dev, 0); atomic_inc(&dev->vbl_received);
if (stat & RADEON_CRTC2_VBLANK_STAT) if (stat & RADEON_CRTC2_VBLANK_STAT)
drm_handle_vblank(dev, 1); atomic_inc(&dev->vbl_received2);
} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
(vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
((stat & RADEON_CRTC2_VBLANK_STAT) &&
(vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -175,27 +144,54 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) ...@@ -175,27 +144,54 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
return ret; return ret;
} }
u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) static int radeon_driver_vblank_do_wait(struct drm_device * dev,
unsigned int *sequence, int crtc)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv =
u32 crtc_cnt_reg, crtc_status_reg; (drm_radeon_private_t *) dev->dev_private;
unsigned int cur_vblank;
int ret = 0;
int ack = 0;
atomic_t *counter;
if (!dev_priv) { if (!dev_priv) {
DRM_ERROR("called with no initialization\n"); DRM_ERROR("called with no initialization\n");
return -EINVAL; return -EINVAL;
} }
if (crtc == 0) { if (crtc == DRM_RADEON_VBLANK_CRTC1) {
crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; counter = &dev->vbl_received;
crtc_status_reg = RADEON_CRTC_STATUS; ack |= RADEON_CRTC_VBLANK_STAT;
} else if (crtc == 1) { } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; counter = &dev->vbl_received2;
crtc_status_reg = RADEON_CRTC2_STATUS; ack |= RADEON_CRTC2_VBLANK_STAT;
} else { } else
return -EINVAL; return -EINVAL;
}
return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); radeon_acknowledge_irqs(dev_priv, ack);
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
/* 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(counter))
- *sequence) <= (1 << 23)));
*sequence = cur_vblank;
return ret;
}
int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
{
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
}
int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
{
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
} }
/* Needs the lock as it touches the ring. /* Needs the lock as it touches the ring.
...@@ -238,6 +234,21 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr ...@@ -238,6 +234,21 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
return radeon_wait_irq(dev, irqwait->irq_seq); return radeon_wait_irq(dev, irqwait->irq_seq);
} }
static void radeon_enable_interrupt(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
dev_priv->irq_enabled = 1;
}
/* drm_dma.h hooks /* drm_dma.h hooks
*/ */
void radeon_driver_irq_preinstall(struct drm_device * dev) void radeon_driver_irq_preinstall(struct drm_device * dev)
...@@ -249,27 +260,20 @@ void radeon_driver_irq_preinstall(struct drm_device * dev) ...@@ -249,27 +260,20 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
/* Clear bits if they're already high */ /* Clear bits if they're already high */
radeon_acknowledge_irqs(dev_priv); radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
RADEON_CRTC_VBLANK_STAT |
RADEON_CRTC2_VBLANK_STAT));
} }
int radeon_driver_irq_postinstall(struct drm_device * dev) void radeon_driver_irq_postinstall(struct drm_device * dev)
{ {
drm_radeon_private_t *dev_priv = drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private; (drm_radeon_private_t *) dev->dev_private;
int ret;
atomic_set(&dev_priv->swi_emitted, 0); atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
ret = drm_vblank_init(dev, 2); radeon_enable_interrupt(dev);
if (ret)
return ret;
dev->max_vblank_count = 0x001fffff;
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
return 0;
} }
void radeon_driver_irq_uninstall(struct drm_device * dev) void radeon_driver_irq_uninstall(struct drm_device * dev)
...@@ -311,5 +315,6 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) ...@@ -311,5 +315,6 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
return -EINVAL; return -EINVAL;
} }
dev_priv->vblank_crtc = (unsigned int)value; dev_priv->vblank_crtc = (unsigned int)value;
radeon_enable_interrupt(dev);
return 0; return 0;
} }
...@@ -40,13 +40,11 @@ static struct pci_device_id pciidlist[] = { ...@@ -40,13 +40,11 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
DRIVER_IRQ_SHARED, DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
.load = via_driver_load, .load = via_driver_load,
.unload = via_driver_unload, .unload = via_driver_unload,
.context_dtor = via_final_context, .context_dtor = via_final_context,
.get_vblank_counter = via_get_vblank_counter, .vblank_wait = via_driver_vblank_wait,
.enable_vblank = via_enable_vblank,
.disable_vblank = via_disable_vblank,
.irq_preinstall = via_driver_irq_preinstall, .irq_preinstall = via_driver_irq_preinstall,
.irq_postinstall = via_driver_irq_postinstall, .irq_postinstall = via_driver_irq_postinstall,
.irq_uninstall = via_driver_irq_uninstall, .irq_uninstall = via_driver_irq_uninstall,
......
...@@ -75,7 +75,6 @@ typedef struct drm_via_private { ...@@ -75,7 +75,6 @@ typedef struct drm_via_private {
struct timeval last_vblank; struct timeval last_vblank;
int last_vblank_valid; int last_vblank_valid;
unsigned usec_per_vblank; unsigned usec_per_vblank;
atomic_t vbl_received;
drm_via_state_t hc_state; drm_via_state_t hc_state;
char pci_buf[VIA_PCI_BUF_SIZE]; char pci_buf[VIA_PCI_BUF_SIZE];
const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
...@@ -131,13 +130,11 @@ extern int via_init_context(struct drm_device * dev, int context); ...@@ -131,13 +130,11 @@ extern int via_init_context(struct drm_device * dev, int context);
extern int via_final_context(struct drm_device * dev, int context); extern int via_final_context(struct drm_device * dev, int context);
extern int via_do_cleanup_map(struct drm_device * dev); extern int via_do_cleanup_map(struct drm_device * dev);
extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc); extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
extern int via_enable_vblank(struct drm_device *dev, int crtc);
extern void via_disable_vblank(struct drm_device *dev, int crtc);
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
extern void via_driver_irq_preinstall(struct drm_device * dev); extern void via_driver_irq_preinstall(struct drm_device * dev);
extern int via_driver_irq_postinstall(struct drm_device * dev); extern void via_driver_irq_postinstall(struct drm_device * dev);
extern void via_driver_irq_uninstall(struct drm_device * dev); extern void via_driver_irq_uninstall(struct drm_device * dev);
extern int via_dma_cleanup(struct drm_device * dev); extern int via_dma_cleanup(struct drm_device * dev);
......
...@@ -96,15 +96,6 @@ static unsigned time_diff(struct timeval *now, struct timeval *then) ...@@ -96,15 +96,6 @@ static unsigned time_diff(struct timeval *now, struct timeval *then)
1000000 - (then->tv_usec - now->tv_usec); 1000000 - (then->tv_usec - now->tv_usec);
} }
u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
{
drm_via_private_t *dev_priv = dev->dev_private;
if (crtc != 0)
return 0;
return atomic_read(&dev_priv->vbl_received);
}
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -117,8 +108,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -117,8 +108,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
status = VIA_READ(VIA_REG_INTERRUPT); status = VIA_READ(VIA_REG_INTERRUPT);
if (status & VIA_IRQ_VBLANK_PENDING) { if (status & VIA_IRQ_VBLANK_PENDING) {
atomic_inc(&dev_priv->vbl_received); atomic_inc(&dev->vbl_received);
if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
do_gettimeofday(&cur_vblank); do_gettimeofday(&cur_vblank);
if (dev_priv->last_vblank_valid) { if (dev_priv->last_vblank_valid) {
dev_priv->usec_per_vblank = dev_priv->usec_per_vblank =
...@@ -128,11 +119,12 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -128,11 +119,12 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank = cur_vblank;
dev_priv->last_vblank_valid = 1; dev_priv->last_vblank_valid = 1;
} }
if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
DRM_DEBUG("US per vblank is: %u\n", DRM_DEBUG("US per vblank is: %u\n",
dev_priv->usec_per_vblank); dev_priv->usec_per_vblank);
} }
drm_handle_vblank(dev, 0); DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
handled = 1; handled = 1;
} }
...@@ -171,34 +163,31 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) ...@@ -171,34 +163,31 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
} }
} }
int via_enable_vblank(struct drm_device *dev, int crtc) int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
{ {
drm_via_private_t *dev_priv = dev->dev_private; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status; unsigned int cur_vblank;
int ret = 0;
if (crtc != 0) { DRM_DEBUG("\n");
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL; return -EINVAL;
} }
status = VIA_READ(VIA_REG_INTERRUPT); viadrv_acknowledge_irqs(dev_priv);
VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
VIA_WRITE8(0x83d4, 0x11);
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
return 0;
}
void via_disable_vblank(struct drm_device *dev, int crtc) /* Assume that the user has missed the current sequence number
{ * by about a day rather than she wants to wait for years
drm_via_private_t *dev_priv = dev->dev_private; * using vertical blanks...
*/
VIA_WRITE8(0x83d4, 0x11); DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); (((cur_vblank = atomic_read(&dev->vbl_received)) -
*sequence) <= (1 << 23)));
if (crtc != 0) *sequence = cur_vblank;
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); return ret;
} }
static int static int
...@@ -303,25 +292,23 @@ void via_driver_irq_preinstall(struct drm_device * dev) ...@@ -303,25 +292,23 @@ void via_driver_irq_preinstall(struct drm_device * dev)
} }
} }
int via_driver_irq_postinstall(struct drm_device * dev) void via_driver_irq_postinstall(struct drm_device * dev)
{ {
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status; u32 status;
DRM_DEBUG("via_driver_irq_postinstall\n"); DRM_DEBUG("\n");
if (!dev_priv) if (dev_priv) {
return -EINVAL;
drm_vblank_init(dev, 1);
status = VIA_READ(VIA_REG_INTERRUPT); status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask); | dev_priv->irq_enable_mask);
/* Some magic, oh for some data sheets ! */ /* Some magic, oh for some data sheets ! */
VIA_WRITE8(0x83d4, 0x11); VIA_WRITE8(0x83d4, 0x11);
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
return 0; }
} }
void via_driver_irq_uninstall(struct drm_device * dev) void via_driver_irq_uninstall(struct drm_device * dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment