Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm/i915: Save/restore HWS_PGA on suspend/resume drm: move drm vblank initialization/cleanup to driver load/unload drm/i915: execbuffer pins objects, no need to ensure they're still in the GTT drm/i915: Always read pipestat in irq_handler drm/i915: Subtract total pinned bytes from available aperture size drm/i915: Avoid BUG_ONs on VT switch with a wedged chipset. drm/i915: Remove IMR masking during interrupt handler, and restart it if needed. drm/i915: Manage PIPESTAT to control vblank interrupts instead of IMR.
This commit is contained in:
@@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drm_vblank_cleanup(dev);
|
||||||
|
|
||||||
drm_lastclose(dev);
|
drm_lastclose(dev);
|
||||||
|
|
||||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
||||||
|
@@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drm_vblank_cleanup(struct drm_device *dev)
|
void drm_vblank_cleanup(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
/* Bail if the driver didn't call drm_vblank_init() */
|
/* Bail if the driver didn't call drm_vblank_init() */
|
||||||
if (dev->num_crtcs == 0)
|
if (dev->num_crtcs == 0)
|
||||||
@@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev)
|
|||||||
|
|
||||||
free_irq(dev->pdev->irq, dev);
|
free_irq(dev->pdev->irq, dev);
|
||||||
|
|
||||||
drm_vblank_cleanup(dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_irq_uninstall);
|
EXPORT_SYMBOL(drm_irq_uninstall);
|
||||||
|
@@ -856,6 +856,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||||||
|
|
||||||
spin_lock_init(&dev_priv->user_irq_lock);
|
spin_lock_init(&dev_priv->user_irq_lock);
|
||||||
|
|
||||||
|
ret = drm_vblank_init(dev, I915_NUM_PIPE);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
(void) i915_driver_unload(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,6 +47,8 @@ enum pipe {
|
|||||||
PIPE_B,
|
PIPE_B,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define I915_NUM_PIPE 2
|
||||||
|
|
||||||
/* Interface history:
|
/* Interface history:
|
||||||
*
|
*
|
||||||
* 1.1: Original.
|
* 1.1: Original.
|
||||||
@@ -132,6 +134,7 @@ typedef struct drm_i915_private {
|
|||||||
int user_irq_refcount;
|
int user_irq_refcount;
|
||||||
/** Cached value of IMR to avoid reads in updating the bitfield */
|
/** Cached value of IMR to avoid reads in updating the bitfield */
|
||||||
u32 irq_mask_reg;
|
u32 irq_mask_reg;
|
||||||
|
u32 pipestat[2];
|
||||||
|
|
||||||
int tex_lru_log_granularity;
|
int tex_lru_log_granularity;
|
||||||
int allow_batchbuffer;
|
int allow_batchbuffer;
|
||||||
@@ -147,6 +150,7 @@ typedef struct drm_i915_private {
|
|||||||
u32 saveDSPBCNTR;
|
u32 saveDSPBCNTR;
|
||||||
u32 saveDSPARB;
|
u32 saveDSPARB;
|
||||||
u32 saveRENDERSTANDBY;
|
u32 saveRENDERSTANDBY;
|
||||||
|
u32 saveHWS;
|
||||||
u32 savePIPEACONF;
|
u32 savePIPEACONF;
|
||||||
u32 savePIPEBCONF;
|
u32 savePIPEBCONF;
|
||||||
u32 savePIPEASRC;
|
u32 savePIPEASRC;
|
||||||
@@ -446,6 +450,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
|
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
|
||||||
|
|
||||||
|
void
|
||||||
|
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
|
||||||
|
|
||||||
|
void
|
||||||
|
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
|
||||||
|
|
||||||
|
|
||||||
/* 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,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
#include "i915_drv.h"
|
#include "i915_drv.h"
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
|
|
||||||
|
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
i915_gem_object_set_domain(struct drm_gem_object *obj,
|
i915_gem_object_set_domain(struct drm_gem_object *obj,
|
||||||
uint32_t read_domains,
|
uint32_t read_domains,
|
||||||
@@ -83,20 +85,14 @@ int
|
|||||||
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
||||||
struct drm_i915_gem_get_aperture *args = data;
|
struct drm_i915_gem_get_aperture *args = data;
|
||||||
struct drm_i915_gem_object *obj_priv;
|
|
||||||
|
|
||||||
if (!(dev->driver->driver_features & DRIVER_GEM))
|
if (!(dev->driver->driver_features & DRIVER_GEM))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
args->aper_size = dev->gtt_total;
|
args->aper_size = dev->gtt_total;
|
||||||
args->aper_available_size = args->aper_size;
|
args->aper_available_size = (args->aper_size -
|
||||||
|
atomic_read(&dev->pin_memory));
|
||||||
list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
|
|
||||||
if (obj_priv->pin_count > 0)
|
|
||||||
args->aper_available_size -= obj_priv->obj->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1870,17 +1866,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
for (i = 0; i < args->buffer_count; i++) {
|
for (i = 0; i < args->buffer_count; i++) {
|
||||||
struct drm_gem_object *obj = object_list[i];
|
struct drm_gem_object *obj = object_list[i];
|
||||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
||||||
|
|
||||||
if (obj_priv->gtt_space == NULL) {
|
|
||||||
/* We evicted the buffer in the process of validating
|
|
||||||
* our set of buffers in. We could try to recover by
|
|
||||||
* kicking them everything out and trying again from
|
|
||||||
* the start.
|
|
||||||
*/
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure all previous memory operations have passed */
|
/* make sure all previous memory operations have passed */
|
||||||
ret = i915_gem_object_set_domain(obj,
|
ret = i915_gem_object_set_domain(obj,
|
||||||
@@ -2299,29 +2284,52 @@ i915_gem_idle(struct drm_device *dev)
|
|||||||
|
|
||||||
i915_gem_retire_requests(dev);
|
i915_gem_retire_requests(dev);
|
||||||
|
|
||||||
/* Active and flushing should now be empty as we've
|
if (!dev_priv->mm.wedged) {
|
||||||
* waited for a sequence higher than any pending execbuffer
|
/* Active and flushing should now be empty as we've
|
||||||
*/
|
* waited for a sequence higher than any pending execbuffer
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.active_list));
|
*/
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
|
WARN_ON(!list_empty(&dev_priv->mm.active_list));
|
||||||
|
WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
|
||||||
|
/* Request should now be empty as we've also waited
|
||||||
|
* for the last request in the list
|
||||||
|
*/
|
||||||
|
WARN_ON(!list_empty(&dev_priv->mm.request_list));
|
||||||
|
}
|
||||||
|
|
||||||
/* Request should now be empty as we've also waited
|
/* Empty the active and flushing lists to inactive. If there's
|
||||||
* for the last request in the list
|
* anything left at this point, it means that we're wedged and
|
||||||
|
* nothing good's going to happen by leaving them there. So strip
|
||||||
|
* the GPU domains and just stuff them onto inactive.
|
||||||
*/
|
*/
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.request_list));
|
while (!list_empty(&dev_priv->mm.active_list)) {
|
||||||
|
struct drm_i915_gem_object *obj_priv;
|
||||||
|
|
||||||
/* Move all buffers out of the GTT. */
|
obj_priv = list_first_entry(&dev_priv->mm.active_list,
|
||||||
|
struct drm_i915_gem_object,
|
||||||
|
list);
|
||||||
|
obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||||
|
i915_gem_object_move_to_inactive(obj_priv->obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!list_empty(&dev_priv->mm.flushing_list)) {
|
||||||
|
struct drm_i915_gem_object *obj_priv;
|
||||||
|
|
||||||
|
obj_priv = list_first_entry(&dev_priv->mm.active_list,
|
||||||
|
struct drm_i915_gem_object,
|
||||||
|
list);
|
||||||
|
obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||||
|
i915_gem_object_move_to_inactive(obj_priv->obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Move all inactive buffers out of the GTT. */
|
||||||
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
|
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
|
||||||
|
WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.active_list));
|
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
|
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
|
|
||||||
BUG_ON(!list_empty(&dev_priv->mm.request_list));
|
|
||||||
|
|
||||||
i915_gem_cleanup_ringbuffer(dev);
|
i915_gem_cleanup_ringbuffer(dev);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
@@ -33,11 +33,23 @@
|
|||||||
|
|
||||||
#define MAX_NOPID ((u32)~0)
|
#define MAX_NOPID ((u32)~0)
|
||||||
|
|
||||||
/** These are the interrupts used by the driver */
|
/**
|
||||||
#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
|
* Interrupts that are always left unmasked.
|
||||||
I915_ASLE_INTERRUPT | \
|
*
|
||||||
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
|
* Since pipe events are edge-triggered from the PIPESTAT register to IIR,
|
||||||
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
|
* we leave them always unmasked in IMR and then control enabling them through
|
||||||
|
* PIPESTAT alone.
|
||||||
|
*/
|
||||||
|
#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
|
||||||
|
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
|
||||||
|
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
|
||||||
|
|
||||||
|
/** Interrupts that we mask and unmask at runtime. */
|
||||||
|
#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
|
||||||
|
|
||||||
|
/** These are all of the interrupts used by the driver */
|
||||||
|
#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
|
||||||
|
I915_INTERRUPT_ENABLE_VAR)
|
||||||
|
|
||||||
void
|
void
|
||||||
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
|
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||||
@@ -59,6 +71,41 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
i915_pipestat(int pipe)
|
||||||
|
{
|
||||||
|
if (pipe == 0)
|
||||||
|
return PIPEASTAT;
|
||||||
|
if (pipe == 1)
|
||||||
|
return PIPEBSTAT;
|
||||||
|
BUG_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
|
||||||
|
{
|
||||||
|
if ((dev_priv->pipestat[pipe] & mask) != mask) {
|
||||||
|
u32 reg = i915_pipestat(pipe);
|
||||||
|
|
||||||
|
dev_priv->pipestat[pipe] |= mask;
|
||||||
|
/* Enable the interrupt, clear any pending status */
|
||||||
|
I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
|
||||||
|
(void) I915_READ(reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
|
||||||
|
{
|
||||||
|
if ((dev_priv->pipestat[pipe] & mask) != 0) {
|
||||||
|
u32 reg = i915_pipestat(pipe);
|
||||||
|
|
||||||
|
dev_priv->pipestat[pipe] &= ~mask;
|
||||||
|
I915_WRITE(reg, dev_priv->pipestat[pipe]);
|
||||||
|
(void) I915_READ(reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i915_pipe_enabled - check if a pipe is enabled
|
* i915_pipe_enabled - check if a pipe is enabled
|
||||||
* @dev: DRM device
|
* @dev: DRM device
|
||||||
@@ -121,80 +168,102 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = (struct drm_device *) arg;
|
struct drm_device *dev = (struct drm_device *) arg;
|
||||||
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 iir;
|
u32 iir, new_iir;
|
||||||
u32 pipea_stats, pipeb_stats;
|
u32 pipea_stats, pipeb_stats;
|
||||||
|
u32 vblank_status;
|
||||||
|
u32 vblank_enable;
|
||||||
int vblank = 0;
|
int vblank = 0;
|
||||||
|
unsigned long irqflags;
|
||||||
|
int irq_received;
|
||||||
|
int ret = IRQ_NONE;
|
||||||
|
|
||||||
atomic_inc(&dev_priv->irq_received);
|
atomic_inc(&dev_priv->irq_received);
|
||||||
|
|
||||||
if (dev->pdev->msi_enabled)
|
|
||||||
I915_WRITE(IMR, ~0);
|
|
||||||
iir = I915_READ(IIR);
|
iir = I915_READ(IIR);
|
||||||
|
|
||||||
if (iir == 0) {
|
if (IS_I965G(dev)) {
|
||||||
if (dev->pdev->msi_enabled) {
|
vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
|
||||||
I915_WRITE(IMR, dev_priv->irq_mask_reg);
|
vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
|
||||||
(void) I915_READ(IMR);
|
} else {
|
||||||
}
|
vblank_status = I915_VBLANK_INTERRUPT_STATUS;
|
||||||
return IRQ_NONE;
|
vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
for (;;) {
|
||||||
* Clear the PIPE(A|B)STAT regs before the IIR otherwise
|
irq_received = iir != 0;
|
||||||
* we may get extra interrupts.
|
|
||||||
*/
|
/* Can't rely on pipestat interrupt bit in iir as it might
|
||||||
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
|
* have been cleared after the pipestat interrupt was received.
|
||||||
|
* It doesn't set the bit in iir again, but it still produces
|
||||||
|
* interrupts (for non-MSI).
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||||
pipea_stats = I915_READ(PIPEASTAT);
|
pipea_stats = I915_READ(PIPEASTAT);
|
||||||
if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
|
pipeb_stats = I915_READ(PIPEBSTAT);
|
||||||
pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
|
/*
|
||||||
PIPE_VBLANK_INTERRUPT_ENABLE);
|
* Clear the PIPE(A|B)STAT regs before the IIR
|
||||||
else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
|
*/
|
||||||
PIPE_VBLANK_INTERRUPT_STATUS)) {
|
if (pipea_stats & 0x8000ffff) {
|
||||||
|
I915_WRITE(PIPEASTAT, pipea_stats);
|
||||||
|
irq_received = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipeb_stats & 0x8000ffff) {
|
||||||
|
I915_WRITE(PIPEBSTAT, pipeb_stats);
|
||||||
|
irq_received = 1;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||||
|
|
||||||
|
if (!irq_received)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = IRQ_HANDLED;
|
||||||
|
|
||||||
|
I915_WRITE(IIR, iir);
|
||||||
|
new_iir = I915_READ(IIR); /* Flush posted writes */
|
||||||
|
|
||||||
|
if (dev_priv->sarea_priv)
|
||||||
|
dev_priv->sarea_priv->last_dispatch =
|
||||||
|
READ_BREADCRUMB(dev_priv);
|
||||||
|
|
||||||
|
if (iir & I915_USER_INTERRUPT) {
|
||||||
|
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
|
||||||
|
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipea_stats & vblank_status) {
|
||||||
vblank++;
|
vblank++;
|
||||||
drm_handle_vblank(dev, 0);
|
drm_handle_vblank(dev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
I915_WRITE(PIPEASTAT, pipea_stats);
|
if (pipeb_stats & vblank_status) {
|
||||||
}
|
|
||||||
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
|
|
||||||
pipeb_stats = I915_READ(PIPEBSTAT);
|
|
||||||
/* Ack the event */
|
|
||||||
I915_WRITE(PIPEBSTAT, pipeb_stats);
|
|
||||||
|
|
||||||
/* The vblank interrupt gets enabled even if we didn't ask for
|
|
||||||
it, so make sure it's shut down again */
|
|
||||||
if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
|
|
||||||
pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
|
|
||||||
PIPE_VBLANK_INTERRUPT_ENABLE);
|
|
||||||
else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
|
|
||||||
PIPE_VBLANK_INTERRUPT_STATUS)) {
|
|
||||||
vblank++;
|
vblank++;
|
||||||
drm_handle_vblank(dev, 1);
|
drm_handle_vblank(dev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
|
if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
||||||
|
(iir & I915_ASLE_INTERRUPT))
|
||||||
opregion_asle_intr(dev);
|
opregion_asle_intr(dev);
|
||||||
I915_WRITE(PIPEBSTAT, pipeb_stats);
|
|
||||||
|
/* With MSI, interrupts are only generated when iir
|
||||||
|
* transitions from zero to nonzero. If another bit got
|
||||||
|
* set while we were handling the existing iir bits, then
|
||||||
|
* we would never get another interrupt.
|
||||||
|
*
|
||||||
|
* This is fine on non-MSI as well, as if we hit this path
|
||||||
|
* we avoid exiting the interrupt handler only to generate
|
||||||
|
* another one.
|
||||||
|
*
|
||||||
|
* Note that for MSI this could cause a stray interrupt report
|
||||||
|
* if an interrupt landed in the time between writing IIR and
|
||||||
|
* the posting read. This should be rare enough to never
|
||||||
|
* trigger the 99% of 100,000 interrupts test for disabling
|
||||||
|
* stray interrupts.
|
||||||
|
*/
|
||||||
|
iir = new_iir;
|
||||||
}
|
}
|
||||||
|
|
||||||
I915_WRITE(IIR, iir);
|
return ret;
|
||||||
if (dev->pdev->msi_enabled)
|
|
||||||
I915_WRITE(IMR, dev_priv->irq_mask_reg);
|
|
||||||
(void) I915_READ(IIR); /* Flush posted writes */
|
|
||||||
|
|
||||||
if (dev_priv->sarea_priv)
|
|
||||||
dev_priv->sarea_priv->last_dispatch =
|
|
||||||
READ_BREADCRUMB(dev_priv);
|
|
||||||
|
|
||||||
if (iir & I915_USER_INTERRUPT) {
|
|
||||||
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
|
|
||||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iir & I915_ASLE_INTERRUPT)
|
|
||||||
opregion_asle_intr(dev);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i915_emit_irq(struct drm_device * dev)
|
static int i915_emit_irq(struct drm_device * dev)
|
||||||
@@ -330,48 +399,16 @@ int i915_irq_wait(struct drm_device *dev, void *data,
|
|||||||
int i915_enable_vblank(struct drm_device *dev, int pipe)
|
int i915_enable_vblank(struct drm_device *dev, int pipe)
|
||||||
{
|
{
|
||||||
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 pipestat_reg = 0;
|
|
||||||
u32 pipestat;
|
|
||||||
u32 interrupt = 0;
|
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
|
||||||
switch (pipe) {
|
|
||||||
case 0:
|
|
||||||
pipestat_reg = PIPEASTAT;
|
|
||||||
interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pipestat_reg = PIPEBSTAT;
|
|
||||||
interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
|
|
||||||
pipe);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||||
/* Enabling vblank events in IMR comes before PIPESTAT write, or
|
|
||||||
* there's a race where the PIPESTAT vblank bit gets set to 1, so
|
|
||||||
* the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
|
|
||||||
* ISR flashes to 1, but the IIR bit doesn't get set to 1 because
|
|
||||||
* IMR masks it. It doesn't ever get set after we clear the masking
|
|
||||||
* in IMR because the ISR bit is edge, not level-triggered, on the
|
|
||||||
* OR of PIPESTAT bits.
|
|
||||||
*/
|
|
||||||
i915_enable_irq(dev_priv, interrupt);
|
|
||||||
pipestat = I915_READ(pipestat_reg);
|
|
||||||
if (IS_I965G(dev))
|
if (IS_I965G(dev))
|
||||||
pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
|
i915_enable_pipestat(dev_priv, pipe,
|
||||||
|
PIPE_START_VBLANK_INTERRUPT_ENABLE);
|
||||||
else
|
else
|
||||||
pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
|
i915_enable_pipestat(dev_priv, pipe,
|
||||||
/* Clear any stale interrupt status */
|
PIPE_VBLANK_INTERRUPT_ENABLE);
|
||||||
pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
|
|
||||||
PIPE_VBLANK_INTERRUPT_STATUS);
|
|
||||||
I915_WRITE(pipestat_reg, pipestat);
|
|
||||||
(void) I915_READ(pipestat_reg); /* Posting read */
|
|
||||||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,37 +418,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
|
|||||||
void i915_disable_vblank(struct drm_device *dev, int pipe)
|
void i915_disable_vblank(struct drm_device *dev, int pipe)
|
||||||
{
|
{
|
||||||
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 pipestat_reg = 0;
|
|
||||||
u32 pipestat;
|
|
||||||
u32 interrupt = 0;
|
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
|
||||||
switch (pipe) {
|
|
||||||
case 0:
|
|
||||||
pipestat_reg = PIPEASTAT;
|
|
||||||
interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pipestat_reg = PIPEBSTAT;
|
|
||||||
interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
|
|
||||||
pipe);
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||||
i915_disable_irq(dev_priv, interrupt);
|
i915_disable_pipestat(dev_priv, pipe,
|
||||||
pipestat = I915_READ(pipestat_reg);
|
PIPE_VBLANK_INTERRUPT_ENABLE |
|
||||||
pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
|
PIPE_START_VBLANK_INTERRUPT_ENABLE);
|
||||||
PIPE_VBLANK_INTERRUPT_ENABLE);
|
|
||||||
/* Clear any stale interrupt status */
|
|
||||||
pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
|
|
||||||
PIPE_VBLANK_INTERRUPT_STATUS);
|
|
||||||
I915_WRITE(pipestat_reg, pipestat);
|
|
||||||
(void) I915_READ(pipestat_reg); /* Posting read */
|
|
||||||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,32 +488,35 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|||||||
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;
|
||||||
|
|
||||||
I915_WRITE(HWSTAM, 0xeffe);
|
I915_WRITE(HWSTAM, 0xeffe);
|
||||||
|
I915_WRITE(PIPEASTAT, 0);
|
||||||
|
I915_WRITE(PIPEBSTAT, 0);
|
||||||
I915_WRITE(IMR, 0xffffffff);
|
I915_WRITE(IMR, 0xffffffff);
|
||||||
I915_WRITE(IER, 0x0);
|
I915_WRITE(IER, 0x0);
|
||||||
|
(void) I915_READ(IER);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i915_driver_irq_postinstall(struct drm_device *dev)
|
int i915_driver_irq_postinstall(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
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;
|
||||||
int ret, num_pipes = 2;
|
|
||||||
|
|
||||||
/* Set initial unmasked IRQs to just the selected vblank pipes. */
|
|
||||||
dev_priv->irq_mask_reg = ~0;
|
|
||||||
|
|
||||||
ret = drm_vblank_init(dev, num_pipes);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
|
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
|
||||||
dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
|
|
||||||
dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
|
|
||||||
|
|
||||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||||
|
|
||||||
dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
|
/* Unmask the interrupts that we always want on. */
|
||||||
|
dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
|
||||||
|
|
||||||
|
dev_priv->pipestat[0] = 0;
|
||||||
|
dev_priv->pipestat[1] = 0;
|
||||||
|
|
||||||
|
/* Disable pipe interrupt enables, clear pending pipe status */
|
||||||
|
I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
|
||||||
|
I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
|
||||||
|
/* Clear pending interrupt status */
|
||||||
|
I915_WRITE(IIR, I915_READ(IIR));
|
||||||
|
|
||||||
I915_WRITE(IMR, dev_priv->irq_mask_reg);
|
|
||||||
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
|
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
|
||||||
|
I915_WRITE(IMR, dev_priv->irq_mask_reg);
|
||||||
(void) I915_READ(IER);
|
(void) I915_READ(IER);
|
||||||
|
|
||||||
opregion_enable_asle(dev);
|
opregion_enable_asle(dev);
|
||||||
@@ -513,7 +528,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
|||||||
void i915_driver_irq_uninstall(struct drm_device * dev)
|
void i915_driver_irq_uninstall(struct drm_device * dev)
|
||||||
{
|
{
|
||||||
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 temp;
|
|
||||||
|
|
||||||
if (!dev_priv)
|
if (!dev_priv)
|
||||||
return;
|
return;
|
||||||
@@ -521,13 +535,12 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
|
|||||||
dev_priv->vblank_pipe = 0;
|
dev_priv->vblank_pipe = 0;
|
||||||
|
|
||||||
I915_WRITE(HWSTAM, 0xffffffff);
|
I915_WRITE(HWSTAM, 0xffffffff);
|
||||||
|
I915_WRITE(PIPEASTAT, 0);
|
||||||
|
I915_WRITE(PIPEBSTAT, 0);
|
||||||
I915_WRITE(IMR, 0xffffffff);
|
I915_WRITE(IMR, 0xffffffff);
|
||||||
I915_WRITE(IER, 0x0);
|
I915_WRITE(IER, 0x0);
|
||||||
|
|
||||||
temp = I915_READ(PIPEASTAT);
|
I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
|
||||||
I915_WRITE(PIPEASTAT, temp);
|
I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
|
||||||
temp = I915_READ(PIPEBSTAT);
|
I915_WRITE(IIR, I915_READ(IIR));
|
||||||
I915_WRITE(PIPEBSTAT, temp);
|
|
||||||
temp = I915_READ(IIR);
|
|
||||||
I915_WRITE(IIR, temp);
|
|
||||||
}
|
}
|
||||||
|
@@ -235,17 +235,15 @@ void opregion_enable_asle(struct drm_device *dev)
|
|||||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||||
|
|
||||||
if (asle) {
|
if (asle) {
|
||||||
u32 pipeb_stats = I915_READ(PIPEBSTAT);
|
|
||||||
if (IS_MOBILE(dev)) {
|
if (IS_MOBILE(dev)) {
|
||||||
/* Many devices trigger events with a write to the
|
unsigned long irqflags;
|
||||||
legacy backlight controller, so we need to ensure
|
|
||||||
that it's able to generate interrupts */
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||||
I915_WRITE(PIPEBSTAT, pipeb_stats |=
|
i915_enable_pipestat(dev_priv, 1,
|
||||||
I915_LEGACY_BLC_EVENT_ENABLE);
|
I915_LEGACY_BLC_EVENT_ENABLE);
|
||||||
i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
|
spin_unlock_irqrestore(&dev_priv->user_irq_lock,
|
||||||
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
|
irqflags);
|
||||||
} else
|
}
|
||||||
i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
|
|
||||||
|
|
||||||
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
|
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
|
||||||
ASLE_PFMB_EN;
|
ASLE_PFMB_EN;
|
||||||
|
@@ -244,6 +244,9 @@ int i915_save_state(struct drm_device *dev)
|
|||||||
if (IS_I965G(dev) && IS_MOBILE(dev))
|
if (IS_I965G(dev) && IS_MOBILE(dev))
|
||||||
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
|
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
|
||||||
|
|
||||||
|
/* Hardware status page */
|
||||||
|
dev_priv->saveHWS = I915_READ(HWS_PGA);
|
||||||
|
|
||||||
/* Display arbitration control */
|
/* Display arbitration control */
|
||||||
dev_priv->saveDSPARB = I915_READ(DSPARB);
|
dev_priv->saveDSPARB = I915_READ(DSPARB);
|
||||||
|
|
||||||
@@ -373,6 +376,9 @@ int i915_restore_state(struct drm_device *dev)
|
|||||||
if (IS_I965G(dev) && IS_MOBILE(dev))
|
if (IS_I965G(dev) && IS_MOBILE(dev))
|
||||||
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
|
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
|
||||||
|
|
||||||
|
/* Hardware status page */
|
||||||
|
I915_WRITE(HWS_PGA, dev_priv->saveHWS);
|
||||||
|
|
||||||
/* Display arbitration */
|
/* Display arbitration */
|
||||||
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
|
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
|
||||||
|
|
||||||
|
@@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
|
|||||||
int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
||||||
{
|
{
|
||||||
drm_mga_private_t *dev_priv;
|
drm_mga_private_t *dev_priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
|
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
|
||||||
if (!dev_priv)
|
if (!dev_priv)
|
||||||
@@ -415,6 +416,13 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
|||||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||||
|
|
||||||
|
ret = drm_vblank_init(dev, 1);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
(void) mga_driver_unload(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -152,11 +152,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
|
|||||||
int mga_driver_irq_postinstall(struct drm_device *dev)
|
int mga_driver_irq_postinstall(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
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);
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ static struct drm_driver driver = {
|
|||||||
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,
|
||||||
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
|
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
|
||||||
|
.load = r128_driver_load,
|
||||||
.preclose = r128_driver_preclose,
|
.preclose = r128_driver_preclose,
|
||||||
.lastclose = r128_driver_lastclose,
|
.lastclose = r128_driver_lastclose,
|
||||||
.get_vblank_counter = r128_get_vblank_counter,
|
.get_vblank_counter = r128_get_vblank_counter,
|
||||||
@@ -84,6 +85,11 @@ static struct drm_driver driver = {
|
|||||||
.patchlevel = DRIVER_PATCHLEVEL,
|
.patchlevel = DRIVER_PATCHLEVEL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int r128_driver_load(struct drm_device * dev, unsigned long flags)
|
||||||
|
{
|
||||||
|
return drm_vblank_init(dev, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int __init r128_init(void)
|
static int __init r128_init(void)
|
||||||
{
|
{
|
||||||
driver.num_ioctls = r128_max_ioctl;
|
driver.num_ioctls = r128_max_ioctl;
|
||||||
|
@@ -159,6 +159,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev);
|
|||||||
extern int r128_driver_irq_postinstall(struct drm_device *dev);
|
extern int 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 int r128_driver_load(struct drm_device * dev, unsigned long flags);
|
||||||
extern void r128_driver_preclose(struct drm_device * dev,
|
extern void r128_driver_preclose(struct drm_device * dev,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
|
||||||
|
@@ -102,7 +102,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
|
|||||||
|
|
||||||
int r128_driver_irq_postinstall(struct drm_device *dev)
|
int r128_driver_irq_postinstall(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
return drm_vblank_init(dev, 1);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void r128_driver_irq_uninstall(struct drm_device * dev)
|
void r128_driver_irq_uninstall(struct drm_device * dev)
|
||||||
|
@@ -1757,6 +1757,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = drm_vblank_init(dev, 2);
|
||||||
|
if (ret) {
|
||||||
|
radeon_driver_unload(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DRM_DEBUG("%s card detected\n",
|
DRM_DEBUG("%s card detected\n",
|
||||||
((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
|
((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -337,15 +337,10 @@ int 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);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
dev->max_vblank_count = 0x001fffff;
|
dev->max_vblank_count = 0x001fffff;
|
||||||
|
|
||||||
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
|
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
|
||||||
|
@@ -314,7 +314,6 @@ int via_driver_irq_postinstall(struct drm_device *dev)
|
|||||||
if (!dev_priv)
|
if (!dev_priv)
|
||||||
return -EINVAL;
|
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);
|
||||||
|
@@ -107,8 +107,17 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset)
|
|||||||
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
|
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
|
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
ret = drm_vblank_init(dev, 1);
|
||||||
|
if (ret) {
|
||||||
|
drm_sman_takedown(&dev_priv->sman);
|
||||||
|
drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int via_driver_unload(struct drm_device *dev)
|
int via_driver_unload(struct drm_device *dev)
|
||||||
|
@@ -1151,6 +1151,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
|
|||||||
extern void drm_handle_vblank(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 int drm_vblank_get(struct drm_device *dev, int crtc);
|
||||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||||
|
extern void drm_vblank_cleanup(struct drm_device *dev);
|
||||||
/* Modesetting support */
|
/* Modesetting support */
|
||||||
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
|
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
Reference in New Issue
Block a user