Commit af6061af authored by Dave Airlie's avatar Dave Airlie

Revert "drm/vbl rework: rework how the drm deals with vblank."

This reverts commit ac741ab7.

Okay this looks like wasn't as fully baked as I'd led myself to believe.

Revert for now for further baking.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c0a18111
...@@ -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);
......
This diff is collapsed.
...@@ -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.
*/ */
......
...@@ -533,7 +533,8 @@ static struct drm_driver driver = { ...@@ -533,7 +533,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 +542,8 @@ static struct drm_driver driver = { ...@@ -541,9 +542,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;
...@@ -222,7 +216,7 @@ extern void i915_driver_preclose(struct drm_device *dev, ...@@ -222,7 +216,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 +227,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc ...@@ -233,7 +227,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 +235,6 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, ...@@ -241,9 +235,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 +379,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -388,91 +379,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 I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
#define PIPE_FRAME_LOW_SHIFT 24 #define I915_VBLANK_CLEAR (1UL<<1)
/*
* 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_OVERLAY_UPDATED_ENABLE (1UL<<16)
#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
......
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) if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
drm_handle_vblank(dev, 0); int vblank_crtc = dev_priv->vblank_crtc;
if (stat & RADEON_CRTC2_VBLANK_STAT)
drm_handle_vblank(dev, 1); 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)
atomic_inc(&dev->vbl_received);
if (stat & RADEON_CRTC2_VBLANK_STAT)
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);
......
...@@ -92,17 +92,8 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; ...@@ -92,17 +92,8 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
static unsigned time_diff(struct timeval *now, struct timeval *then) static unsigned time_diff(struct timeval *now, struct timeval *then)
{ {
return (now->tv_usec >= then->tv_usec) ? return (now->tv_usec >= then->tv_usec) ?
now->tv_usec - then->tv_usec : now->tv_usec - then->tv_usec :
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)
...@@ -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); /* Assume that the user has missed the current sequence number
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); * by about a day rather than she wants to wait for years
* using vertical blanks...
*/
return 0; DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
} (((cur_vblank = atomic_read(&dev->vbl_received)) -
*sequence) <= (1 << 23)));
void via_disable_vblank(struct drm_device *dev, int crtc) *sequence = cur_vblank;
{ return ret;
drm_via_private_t *dev_priv = dev->dev_private;
VIA_WRITE8(0x83d4, 0x11);
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
if (crtc != 0)
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
} }
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; status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask);
drm_vblank_init(dev, 1); /* Some magic, oh for some data sheets ! */
status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask);
/* 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