Merge commit 'origin/drm-gem' into ms-gem

Conflicts:

	linux-core/drmP.h
	linux-core/drm_drv.c
	linux-core/drm_stub.c
	linux-core/i915_drv.c
	linux-core/i915_gem.c
	shared-core/i915_drv.h
	shared-core/i915_irq.c
main
Kristian Høgsberg 2008-07-07 15:43:43 -04:00
commit 3e02f7fd31
11 changed files with 807 additions and 279 deletions

View File

@ -109,11 +109,11 @@ struct _dri_bo_gem {
int validate_index; int validate_index;
/** /**
* Boolean whether set_domain to CPU is current * Boolean whether we've started swrast
* Set when set_domain has been called * Set when the buffer has been mapped
* Cleared when a batch has been submitted * Cleared when the buffer is unmapped
*/ */
int cpu_domain_set; int swrast;
/** Array passed to the DRM containing relocation information. */ /** Array passed to the DRM containing relocation information. */
struct drm_i915_gem_relocation_entry *relocs; struct drm_i915_gem_relocation_entry *relocs;
@ -485,25 +485,27 @@ dri_gem_bo_map(dri_bo *bo, int write_enable)
bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr; bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
} }
bo->virtual = bo_gem->virtual; bo->virtual = bo_gem->virtual;
bo_gem->swrast = 0;
bo_gem->mapped = 1; bo_gem->mapped = 1;
DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual); DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
} }
if (!bo_gem->cpu_domain_set) { if (!bo_gem->swrast) {
set_domain.handle = bo_gem->gem_handle; set_domain.handle = bo_gem->gem_handle;
set_domain.read_domains = I915_GEM_DOMAIN_CPU; set_domain.read_domains = I915_GEM_DOMAIN_CPU;
set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_CPU : 0; if (write_enable)
set_domain.write_domain = I915_GEM_DOMAIN_CPU;
else
set_domain.write_domain = 0;
do { do {
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
&set_domain); &set_domain);
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
if (ret != 0) { if (ret != 0) {
fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n", fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
__FILE__, __LINE__, __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
strerror (errno));
} }
bo_gem->cpu_domain_set = 1; bo_gem->swrast = 1;
} }
return 0; return 0;
@ -512,13 +514,24 @@ dri_gem_bo_map(dri_bo *bo, int write_enable)
static int static int
dri_gem_bo_unmap(dri_bo *bo) dri_gem_bo_unmap(dri_bo *bo)
{ {
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo; dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
struct drm_i915_gem_sw_finish sw_finish;
int ret;
if (bo == NULL) if (bo == NULL)
return 0; return 0;
assert(bo_gem->mapped); assert(bo_gem->mapped);
if (bo_gem->swrast) {
sw_finish.handle = bo_gem->gem_handle;
do {
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
&sw_finish);
} while (ret == -1 && errno == EINTR);
bo_gem->swrast = 0;
}
return 0; return 0;
} }
@ -583,7 +596,7 @@ dri_gem_bo_wait_rendering(dri_bo *bo)
int ret; int ret;
set_domain.handle = bo_gem->gem_handle; set_domain.handle = bo_gem->gem_handle;
set_domain.read_domains = I915_GEM_DOMAIN_CPU; set_domain.read_domains = I915_GEM_DOMAIN_GTT;
set_domain.write_domain = 0; set_domain.write_domain = 0;
ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
if (ret != 0) { if (ret != 0) {
@ -744,8 +757,8 @@ dri_gem_post_submit(dri_bo *batch_buf)
dri_bo *bo = bufmgr_gem->exec_bos[i]; dri_bo *bo = bufmgr_gem->exec_bos[i];
dri_bo_gem *bo_gem = (dri_bo_gem *)bo; dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
/* Need to call set_domain on next bo_map */ /* Need to call swrast on next bo_map */
bo_gem->cpu_domain_set = 0; bo_gem->swrast = 0;
/* Disconnect the buffer from the validate list */ /* Disconnect the buffer from the validate list */
bo_gem->validate_index = -1; bo_gem->validate_index = -1;

View File

@ -811,6 +811,10 @@ struct drm_driver {
/* Master routines */ /* Master routines */
int (*master_create)(struct drm_device *dev, struct drm_master *master); int (*master_create)(struct drm_device *dev, struct drm_master *master);
void (*master_destroy)(struct drm_device *dev, struct drm_master *master); void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
int (*proc_init)(struct drm_minor *minor);
void (*proc_cleanup)(struct drm_minor *minor);
/** /**
* Driver-specific constructor for drm_gem_objects, to set up * Driver-specific constructor for drm_gem_objects, to set up
* obj->driver_private. * obj->driver_private.
@ -1366,7 +1370,7 @@ extern void drm_put_master(struct drm_master *master);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver); struct drm_driver *driver);
extern int drm_put_dev(struct drm_device *dev); extern int drm_put_dev(struct drm_device *dev);
extern int drm_put_minor(struct drm_minor **minor); extern int drm_put_minor(struct drm_device *dev, struct drm_minor **p);
extern unsigned int drm_debug; /* 1 to enable debug output */ extern unsigned int drm_debug; /* 1 to enable debug output */
extern struct class *drm_class; extern struct class *drm_class;

View File

@ -353,7 +353,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
#endif #endif
#if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIMEM)) #if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIGHMEM))
#define DRM_KMAP_ATOMIC_PROT_PFN #define DRM_KMAP_ATOMIC_PROT_PFN
extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
pgprot_t protection); pgprot_t protection);

View File

@ -424,9 +424,10 @@ static void drm_cleanup(struct drm_device * dev)
drm_memrange_takedown(&dev->offset_manager); drm_memrange_takedown(&dev->offset_manager);
drm_ht_remove(&dev->object_hash); drm_ht_remove(&dev->object_hash);
drm_put_minor(&dev->primary); drm_put_minor(dev, &dev->primary);
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control); drm_put_minor(dev, &dev->control);
if (drm_put_dev(dev)) if (drm_put_dev(dev))
DRM_ERROR("Cannot unload module\n"); DRM_ERROR("Cannot unload module\n");
} }

View File

@ -309,6 +309,13 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
DRM_ERROR("DRM: Failed to initialize /proc/dri.\n"); DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
goto err_mem; goto err_mem;
} }
if (dev->driver->proc_init) {
ret = dev->driver->proc_init(new_minor);
if (ret) {
DRM_ERROR("DRM: Driver failed to initialize /proc/dri.\n");
goto err_mem;
}
}
} else } else
new_minor->dev_root = NULL; new_minor->dev_root = NULL;
@ -325,8 +332,11 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
err_g2: err_g2:
if (new_minor->type == DRM_MINOR_LEGACY) if (new_minor->type == DRM_MINOR_LEGACY) {
if (dev->driver->proc_cleanup)
dev->driver->proc_cleanup(new_minor);
drm_proc_cleanup(new_minor, drm_proc_root); drm_proc_cleanup(new_minor, drm_proc_root);
}
err_mem: err_mem:
kfree(new_minor); kfree(new_minor);
err_idr: err_idr:
@ -398,10 +408,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return 0; return 0;
err_g5: err_g5:
drm_put_minor(&dev->primary); drm_put_minor(dev, &dev->primary);
err_g4: err_g4:
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control); drm_put_minor(dev, &dev->control);
err_g3: err_g3:
if (!drm_fb_loaded) if (!drm_fb_loaded)
pci_disable_device(pdev); pci_disable_device(pdev);
@ -452,13 +462,16 @@ int drm_put_dev(struct drm_device * dev)
* last minor released. * last minor released.
* *
*/ */
int drm_put_minor(struct drm_minor **minor_p) int drm_put_minor(struct drm_device *dev, struct drm_minor **minor_p)
{ {
struct drm_minor *minor = *minor_p; struct drm_minor *minor = *minor_p;
DRM_DEBUG("release secondary minor %d\n", minor->index); DRM_DEBUG("release secondary minor %d\n", minor->index);
if (minor->type == DRM_MINOR_LEGACY) if (minor->type == DRM_MINOR_LEGACY) {
if (dev->driver->proc_cleanup)
dev->driver->proc_cleanup(minor);
drm_proc_cleanup(minor, drm_proc_root); drm_proc_cleanup(minor, drm_proc_root);
}
drm_sysfs_device_remove(minor); drm_sysfs_device_remove(minor);
idr_remove(&drm_minors_idr, minor->index); idr_remove(&drm_minors_idr, minor->index);

View File

@ -600,6 +600,8 @@ static struct drm_driver driver = {
.get_reg_ofs = drm_core_get_reg_ofs, .get_reg_ofs = drm_core_get_reg_ofs,
.master_create = i915_master_create, .master_create = i915_master_create,
.master_destroy = i915_master_destroy, .master_destroy = i915_master_destroy,
.proc_init = i915_gem_proc_init,
.proc_cleanup = i915_gem_proc_cleanup,
.ioctls = i915_ioctls, .ioctls = i915_ioctls,
.gem_init_object = i915_gem_init_object, .gem_init_object = i915_gem_init_object,
.gem_free_object = i915_gem_free_object, .gem_free_object = i915_gem_free_object,

File diff suppressed because it is too large Load Diff

View File

@ -1093,6 +1093,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
}; };
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);

View File

@ -189,6 +189,7 @@ typedef struct drm_i915_sarea {
#define DRM_I915_GEM_PWRITE 0x1d #define DRM_I915_GEM_PWRITE 0x1d
#define DRM_I915_GEM_MMAP 0x1e #define DRM_I915_GEM_MMAP 0x1e
#define DRM_I915_GEM_SET_DOMAIN 0x1f #define DRM_I915_GEM_SET_DOMAIN 0x1f
#define DRM_I915_GEM_SW_FINISH 0x20
#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)
@ -221,6 +222,7 @@ typedef struct drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
/* Asynchronous page flipping: /* Asynchronous page flipping:
*/ */
@ -505,6 +507,11 @@ struct drm_i915_gem_set_domain {
uint32_t write_domain; uint32_t write_domain;
}; };
struct drm_i915_gem_sw_finish {
/** Handle for the object */
uint32_t handle;
};
struct drm_i915_gem_relocation_entry { struct drm_i915_gem_relocation_entry {
/** /**
* Handle of the buffer being pointed to by this relocation entry. * Handle of the buffer being pointed to by this relocation entry.
@ -569,6 +576,8 @@ struct drm_i915_gem_relocation_entry {
#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 #define I915_GEM_DOMAIN_INSTRUCTION 0x00000010
/** Vertex address cache */ /** Vertex address cache */
#define I915_GEM_DOMAIN_VERTEX 0x00000020 #define I915_GEM_DOMAIN_VERTEX 0x00000020
/** GTT domain - aperture and scanout */
#define I915_GEM_DOMAIN_GTT 0x00000040
/** @} */ /** @} */
struct drm_i915_gem_exec_object { struct drm_i915_gem_exec_object {

View File

@ -134,7 +134,6 @@ 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_emitted;
int tex_lru_log_granularity; int tex_lru_log_granularity;
int allow_batchbuffer; int allow_batchbuffer;
@ -235,15 +234,34 @@ struct drm_i915_private {
uint32_t next_gem_seqno; uint32_t next_gem_seqno;
/** /**
* Flag if the X Server, and thus DRM, is not currently in * Waiting sequence number, if any
* control of the device. */
* uint32_t waiting_gem_seqno;
* This is set between LeaveVT and EnterVT. It needs to be
* replaced with a semaphore. It also needs to be /**
* transitioned away from for kernel modesetting. * Last seq seen at irq time
*/ */
int suspended; uint32_t irq_gem_seqno;
/**
* Flag if the X Server, and thus DRM, is not currently in
* control of the device.
*
* This is set between LeaveVT and EnterVT. It needs to be
* replaced with a semaphore. It also needs to be
* transitioned away from for kernel modesetting.
*/
int suspended;
/**
* Flag if the hardware appears to be wedged.
*
* This is set when attempts to idle the device timeout.
* It prevents command submission from occuring and makes
* every pending request fail
*/
int wedged;
} mm; } mm;
struct work_struct user_interrupt_task; struct work_struct user_interrupt_task;
@ -369,6 +387,12 @@ struct drm_i915_gem_object {
*/ */
int active; int active;
/**
* This is set if the object has been written to since last bound
* to the GTT
*/
int dirty;
/** AGP memory structure for our GTT binding. */ /** AGP memory structure for our GTT binding. */
DRM_AGP_MEM *agp_mem; DRM_AGP_MEM *agp_mem;
@ -521,6 +545,8 @@ int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_execbuffer(struct drm_device *dev, void *data, int i915_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_pin_ioctl(struct drm_device *dev, void *data, int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
@ -535,11 +561,14 @@ int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_proc_init(struct drm_minor *minor);
void i915_gem_proc_cleanup(struct drm_minor *minor);
int i915_gem_init_object(struct drm_gem_object *obj); int i915_gem_init_object(struct drm_gem_object *obj);
void i915_gem_free_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj);
int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
void i915_gem_object_unpin(struct drm_gem_object *obj); void i915_gem_object_unpin(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev); void i915_gem_lastclose(struct drm_device *dev);
uint32_t i915_get_gem_seqno(struct drm_device *dev);
void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev);
int i915_gem_init_ringbuffer(struct drm_device *dev); int i915_gem_init_ringbuffer(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev);

View File

@ -42,6 +42,26 @@
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
static inline void
i915_enable_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
if ((dev_priv->irq_mask_reg & mask) != 0) {
dev_priv->irq_mask_reg &= ~mask;
I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IMR);
}
}
static inline void
i915_disable_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
if ((dev_priv->irq_mask_reg & mask) != mask) {
dev_priv->irq_mask_reg |= mask;
I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IMR);
}
}
/** /**
* i915_get_pipe - return the the pipe associated with a given plane * i915_get_pipe - return the the pipe associated with a given plane
* @dev: DRM device * @dev: DRM device
@ -510,17 +530,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
int hotplug = 0; int hotplug = 0;
int vblank = 0; int vblank = 0;
/* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
iir = I915_READ(IIR);
else
iir = I915_READ16(IIR);
if (dev->pdev->msi_enabled) if (dev->pdev->msi_enabled)
I915_WRITE(IER, 0); I915_WRITE(IMR, ~0);
iir = I915_READ(IIR);
if (!iir) #if 0
DRM_DEBUG("flag=%08x\n", iir);
#endif
atomic_inc(&dev_priv->irq_received);
if (iir == 0) {
DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
iir,
I915_READ(IMR),
I915_READ(IER),
I915_READ(PIPEASTAT),
I915_READ(PIPEBSTAT));
if (dev->pdev->msi_enabled) {
I915_WRITE(IMR,
dev_priv->irq_mask_reg);
(void) I915_READ(IMR);
}
return IRQ_NONE; return IRQ_NONE;
}
/* /*
* Clear the PIPE(A|B)STAT regs before the IIR otherwise * Clear the PIPE(A|B)STAT regs before the IIR otherwise
@ -528,46 +558,29 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
*/ */
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
pipea_stats = I915_READ(PIPEASTAT); pipea_stats = I915_READ(PIPEASTAT);
if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS))
{
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 0));
}
/* This is a global event, and not a pipe A event */
if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS)
hotplug = 1;
if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) {
hotplug = 1;
/* Toggle hotplug detection to clear hotplug status */
tvdac = I915_READ(TV_DAC);
I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN);
I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN);
}
I915_WRITE(PIPEASTAT, pipea_stats); I915_WRITE(PIPEASTAT, pipea_stats);
} }
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
pipeb_stats = I915_READ(PIPEBSTAT); pipeb_stats = I915_READ(PIPEBSTAT);
if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS))
{
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 1));
}
I915_WRITE(PIPEBSTAT, pipeb_stats); I915_WRITE(PIPEBSTAT, pipeb_stats);
} }
/* Clear the generated interrupt */ I915_WRITE(IIR, iir);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { if (dev->pdev->msi_enabled)
I915_WRITE(IIR, iir); I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IIR); (void) I915_READ(IIR); /* Flush posted writes */
} else {
I915_WRITE16(IIR, iir); /* This is a global event, and not a pipe A event */
(void) I915_READ16(IIR); if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS)
hotplug = 1;
if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) {
hotplug = 1;
/* Toggle hotplug detection to clear hotplug status */
tvdac = I915_READ(TV_DAC);
I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN);
I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN);
} }
if (dev->primary->master) { if (dev->primary->master) {
@ -576,22 +589,25 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
} }
if (iir & I915_USER_INTERRUPT) { if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue); DRM_WAKEUP(&dev_priv->irq_queue);
#ifdef I915_HAVE_FENCE #ifdef I915_HAVE_FENCE
i915_fence_handler(dev); i915_fence_handler(dev);
#endif #endif
} }
if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS| if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
I915_VBLANK_INTERRUPT_STATUS)) { PIPE_VBLANK_INTERRUPT_STATUS)) {
vblank = 1; vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 0)); drm_handle_vblank(dev, i915_get_plane(dev, 0));
} }
if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
I915_VBLANK_INTERRUPT_STATUS)) { if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
vblank = 1; PIPE_VBLANK_INTERRUPT_STATUS)) {
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 1)); drm_handle_vblank(dev, i915_get_plane(dev, 1));
} }
if (vblank) { if (vblank) {
if (dev_priv->swaps_pending > 0) if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet); drm_locked_tasklet(dev, i915_vblank_tasklet);
@ -616,9 +632,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
i915_run_hotplug_tasklet(dev, temp2); i915_run_hotplug_tasklet(dev, temp2);
} }
if (dev->pdev->msi_enabled)
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -646,16 +659,9 @@ void i915_user_irq_on(struct drm_device *dev)
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
DRM_SPINLOCK(&dev_priv->user_irq_lock); DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1))
dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(IMR, dev_priv->irq_mask_reg);
else
I915_WRITE16(IMR, dev_priv->irq_mask_reg);
I915_READ16(IMR);
}
DRM_SPINUNLOCK(&dev_priv->user_irq_lock); DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
} }
void i915_user_irq_off(struct drm_device *dev) void i915_user_irq_off(struct drm_device *dev)
@ -664,14 +670,8 @@ void i915_user_irq_off(struct drm_device *dev)
DRM_SPINLOCK(&dev_priv->user_irq_lock); DRM_SPINLOCK(&dev_priv->user_irq_lock);
BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0);
if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0))
dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(IMR, dev_priv->irq_mask_reg);
else
I915_WRITE16(IMR, dev_priv->irq_mask_reg);
I915_READ16(IMR);
}
DRM_SPINUNLOCK(&dev_priv->user_irq_lock); DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
} }
@ -803,11 +803,7 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
} }
DRM_SPINLOCK(&dev_priv->user_irq_lock); DRM_SPINLOCK(&dev_priv->user_irq_lock);
dev_priv->irq_mask_reg &= ~mask_reg; i915_enable_irq(dev_priv, mask_reg);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(IMR, dev_priv->irq_mask_reg);
else
I915_WRITE16(IMR, dev_priv->irq_mask_reg);
DRM_SPINUNLOCK(&dev_priv->user_irq_lock); DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
return 0; return 0;
@ -837,11 +833,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
} }
DRM_SPINLOCK(&dev_priv->user_irq_lock); DRM_SPINLOCK(&dev_priv->user_irq_lock);
dev_priv->irq_mask_reg |= mask_reg; i915_disable_irq(dev_priv, mask_reg);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(IMR, dev_priv->irq_mask_reg);
else
I915_WRITE16(IMR, dev_priv->irq_mask_reg);
DRM_SPINUNLOCK(&dev_priv->user_irq_lock); DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
if (pipestat_reg) { if (pipestat_reg) {
@ -862,8 +854,8 @@ void i915_enable_interrupt (struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
struct drm_connector *o; struct drm_connector *o;
dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; dev_priv->irq_mask_reg &= ~0;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
if (dev->mode_config.num_connector) if (dev->mode_config.num_connector)
@ -925,14 +917,9 @@ void i915_enable_interrupt (struct drm_device *dev)
} }
} }
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { I915_WRITE(IMR, dev_priv->irq_mask_reg);
I915_WRITE(IMR, dev_priv->irq_mask_reg); I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
I915_WRITE(IER, ~dev_priv->irq_mask_reg); (void) I915_READ (IER);
} else {
I915_WRITE16(IMR, dev_priv->irq_mask_reg);
I915_WRITE16(IER, ~(u16)dev_priv->irq_mask_reg);
}
dev_priv->irq_enabled = 1; dev_priv->irq_enabled = 1;
} }
@ -964,17 +951,15 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_vblank_pipe *pipe = data; struct drm_i915_vblank_pipe *pipe = data;
u16 flag; u32 flag = 0;
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 (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) if (dev_priv->irq_enabled)
flag = I915_READ(IER); flag = ~dev_priv->irq_mask_reg;
else
flag = I915_READ16(IER);
pipe->pipe = 0; pipe->pipe = 0;
if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
@ -1158,19 +1143,12 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
tmp = I915_READ(PIPEBSTAT); tmp = I915_READ(PIPEBSTAT);
I915_WRITE(PIPEBSTAT, tmp); I915_WRITE(PIPEBSTAT, tmp);
atomic_set(&dev_priv->irq_received, 0);
I915_WRITE16(HWSTAM, 0xeffe); I915_WRITE(HWSTAM, 0xffff);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { I915_WRITE(IER, 0x0);
I915_WRITE(IMR, 0x0); I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0); I915_WRITE(IIR, 0xffffffff);
tmp = I915_READ(IIR); (void) I915_READ(IIR);
I915_WRITE(IIR, tmp);
} else {
I915_WRITE16(IMR, 0x0);
I915_WRITE16(IER, 0x0);
tmp = I915_READ16(IIR);
I915_WRITE16(IIR, tmp);
}
} }
int i915_driver_irq_postinstall(struct drm_device * dev) int i915_driver_irq_postinstall(struct drm_device * dev)