Merge branch 'modesetting-101' of ssh://git.freedesktop.org/git/mesa/drm into modesetting-101

main
Jerome Glisse 2008-03-20 17:44:32 +01:00 committed by John Doe
commit 71b66b0043
31 changed files with 869 additions and 348 deletions

View File

@ -2977,3 +2977,20 @@ void drmCloseOnce(int fd)
}
}
}
int drmSetMaster(int fd)
{
int ret;
fprintf(stderr,"Setting master \n");
ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
return ret;
}
int drmDropMaster(int fd)
{
int ret;
fprintf(stderr,"Dropping master \n");
ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
return ret;
}

View File

@ -660,6 +660,9 @@ extern int drmSLLookupNeighbors(void *l, unsigned long key,
extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
extern void drmCloseOnce(int fd);
extern int drmSetMaster(int fd);
extern int drmDropMaster(int fd);
#include "xf86mm.h"
#endif

View File

@ -591,6 +591,13 @@ struct drm_vbl_sig {
struct task_struct *task;
};
struct drm_hotplug_sig {
struct list_head head;
unsigned int counter;
struct siginfo info;
struct task_struct *task;
};
/* location of GART table */
#define DRM_ATI_GART_MAIN 1
#define DRM_ATI_GART_FB 2
@ -867,6 +874,15 @@ struct drm_device {
struct work_struct work;
/** \name HOTPLUG IRQ support */
/*@{ */
wait_queue_head_t hotplug_queue; /**< HOTPLUG wait queue */
spinlock_t hotplug_lock;
struct list_head *hotplug_sigs; /**< signal list to send on HOTPLUG */
atomic_t hotplug_signal_pending; /* number of signals pending on all crtcs*/
/*@} */
/** \name VBLANK IRQ support */
/*@{ */
@ -1060,8 +1076,10 @@ extern int drm_unbind_agp(DRM_AGP_MEM * handle);
extern void drm_free_memctl(size_t size);
extern int drm_alloc_memctl(size_t size);
extern void drm_query_memctl(uint64_t *cur_used,
uint64_t *emer_used,
uint64_t *low_threshold,
uint64_t *high_threshold);
uint64_t *high_threshold,
uint64_t *emer_threshold);
extern void drm_init_memctl(size_t low_threshold,
size_t high_threshold,
size_t unit_size);
@ -1193,13 +1211,17 @@ 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_uninstall(struct drm_device *dev);
extern int drm_hotplug_init(struct drm_device *dev);
extern int drm_wait_hotplug(struct drm_device *dev, void *data, struct drm_file *filp);
extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
extern int drm_wait_hotplug(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 void drm_handle_hotplug(struct drm_device *dev);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);
@ -1244,6 +1266,10 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
extern struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev);
extern void drm_agp_chipset_flush(struct drm_device *dev);
/* Stub support (drm_stub.h) */
extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern struct drm_master *drm_get_master(struct drm_minor *minor);
extern void drm_put_master(struct drm_master *master);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,

View File

@ -208,9 +208,8 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
if (ret)
goto out_err;
}
}
if ((bo->mem.mem_type == DRM_BO_MEM_LOCAL) && bo->ttm == NULL) {
if (bo->mem.mem_type == DRM_BO_MEM_LOCAL) {
struct drm_bo_mem_reg *old_mem = &bo->mem;
uint64_t save_flags = old_mem->flags;
@ -219,25 +218,25 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
*old_mem = *mem;
mem->mm_node = NULL;
old_mem->proposed_flags = save_proposed_flags;
DRM_FLAG_MASKED(save_flags, mem->flags, DRM_BO_MASK_MEMTYPE);
} else if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
!(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED)) {
ret = drm_bo_move_ttm(bo, evict, no_wait, mem);
} else if (dev->driver->bo_driver->move) {
ret = dev->driver->bo_driver->move(bo, evict, no_wait, mem);
} else {
ret = drm_bo_move_memcpy(bo, evict, no_wait, mem);
DRM_FLAG_MASKED(save_flags, mem->flags,
DRM_BO_MASK_MEMTYPE);
goto moved;
}
}
if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
!(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED))
ret = drm_bo_move_ttm(bo, evict, no_wait, mem);
else if (dev->driver->bo_driver->move)
ret = dev->driver->bo_driver->move(bo, evict, no_wait, mem);
else
ret = drm_bo_move_memcpy(bo, evict, no_wait, mem);
if (ret)
goto out_err;
moved:
if (old_is_pci || new_is_pci)
drm_bo_vm_post_move(bo);
@ -789,6 +788,11 @@ static int drm_bo_mem_force_space(struct drm_device *dev,
}
node = drm_mm_get_block(node, num_pages, mem->page_alignment);
if (unlikely(!node)) {
mutex_unlock(&dev->struct_mutex);
return -ENOMEM;
}
mutex_unlock(&dev->struct_mutex);
mem->mm_node = node;
mem->mem_type = mem_type;
@ -974,6 +978,20 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,
return -EPERM;
}
if (likely(new_mask & DRM_BO_MASK_MEM) &&
(bo->mem.flags & DRM_BO_FLAG_NO_EVICT) &&
!DRM_SUSER(DRM_CURPROC)) {
if (likely(bo->mem.flags & new_flags & new_mask &
DRM_BO_MASK_MEM))
new_flags = (new_flags & ~DRM_BO_MASK_MEM) |
(bo->mem.flags & DRM_BO_MASK_MEM);
else {
DRM_ERROR("Incompatible memory type specification "
"for NO_EVICT buffer.\n");
return -EPERM;
}
}
if ((new_flags & DRM_BO_FLAG_NO_MOVE)) {
DRM_ERROR("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n");
return -EPERM;
@ -1482,6 +1500,9 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
if (ret) {
if (ret != -EAGAIN)
DRM_ERROR("Failed moving buffer.\n");
if (ret == -ENOMEM)
DRM_ERROR("Out of aperture space or "
"DRM memory quota.\n");
return ret;
}
}
@ -2748,7 +2769,7 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
list->file_offset_node = drm_mm_search_free(&dev->offset_manager,
bo->mem.num_pages, 0, 0);
if (!list->file_offset_node) {
if (unlikely(!list->file_offset_node)) {
drm_bo_takedown_vm_locked(bo);
return -ENOMEM;
}
@ -2756,6 +2777,11 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
list->file_offset_node = drm_mm_get_block(list->file_offset_node,
bo->mem.num_pages, 0);
if (unlikely(!list->file_offset_node)) {
drm_bo_takedown_vm_locked(bo);
return -ENOMEM;
}
list->hash.key = list->file_offset_node->start;
if (drm_ht_insert_item(&dev->map_hash, &list->hash)) {
drm_bo_takedown_vm_locked(bo);

View File

@ -42,7 +42,6 @@ static void drm_bo_free_old_node(struct drm_buffer_object *bo)
if (old_mem->mm_node && (old_mem->mm_node != bo->pinned_node)) {
mutex_lock(&bo->dev->struct_mutex);
drm_mm_put_block(old_mem->mm_node);
old_mem->mm_node = NULL;
mutex_unlock(&bo->dev->struct_mutex);
}
old_mem->mm_node = NULL;
@ -57,7 +56,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo,
uint64_t save_proposed_flags = old_mem->proposed_flags;
int ret;
if (old_mem->mem_type == DRM_BO_MEM_TT) {
if (old_mem->mem_type != DRM_BO_MEM_LOCAL) {
if (evict)
drm_ttm_evict(ttm);
else

View File

@ -380,10 +380,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
struct drm_map_list *r_list = NULL, *list_t;
drm_dma_handle_t dmah;
int found = 0;
struct drm_master *master;
/* Find the list entry for the map and remove it */
list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
if (r_list->map == map) {
master = r_list->master;
list_del(&r_list->head);
drm_ht_remove_key(&dev->map_hash,
r_list->user_token >> PAGE_SHIFT);
@ -413,9 +415,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
break;
case _DRM_SHM:
vfree(map->handle);
dev->sigdata.lock = dev->primary->master->lock.hw_lock = NULL; /* SHM removed */
dev->primary->master->lock.file_priv = NULL;
wake_up_interruptible(&dev->primary->master->lock.lock_queue);
if (master) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
master->lock.hw_lock = NULL; /* SHM removed */
master->lock.file_priv = NULL;
wake_up_interruptible(&master->lock.lock_queue);
}
break;
case _DRM_AGP:
case _DRM_SCATTER_GATHER:

View File

@ -947,6 +947,7 @@ static void drm_pick_crtcs (struct drm_device *dev)
if (drm_mode_equal (modes, modes_equal)) {
if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) {
printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones);
des_mode = modes;
assigned = 0;
goto clone;
}
@ -1180,7 +1181,7 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info,
* @output hotpluged output
*
* LOCKING.
* Caller must hold mode config lock, function might grap struct lock.
* Caller must hold mode config lock, function might grab struct lock.
*
* Stage two of a hotplug.
*
@ -1192,10 +1193,11 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
{
int has_config = 0;
dev->mode_config.hotplug_counter++;
/* We might want to do something more here */
if (!connected) {
DRM_DEBUG("not connected\n");
dev->mode_config.hotplug_counter++;
return 0;
}
@ -1211,10 +1213,10 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
if (!output->crtc || !output->crtc->desired_mode) {
DRM_DEBUG("could not find a desired mode or crtc for output\n");
goto out_err;
return 1;
}
/* We should realy check if there is a fb using this crtc */
/* We should really check if there is a fb using this crtc */
if (!has_config)
dev->driver->fb_probe(dev, output->crtc);
else {
@ -1226,12 +1228,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
drm_disable_unused_functions(dev);
dev->mode_config.hotplug_counter++;
return 0;
out_err:
dev->mode_config.hotplug_counter++;
return 1;
}
EXPORT_SYMBOL(drm_hotplug_stage_two);

View File

@ -76,6 +76,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@ -136,6 +139,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_ROOT_ONLY | DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_HOTPLUG, drm_mode_hotplug_ioctl, DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_HOTPLUG, drm_wait_hotplug, 0),
DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),

View File

@ -520,8 +520,10 @@ int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class,
struct drm_fence_manager *fm = &dev->fm;
fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
if (!fence)
if (!fence) {
DRM_ERROR("Out of memory creating fence object\n");
return -ENOMEM;
}
ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
if (ret) {
drm_fence_usage_deref_unlocked(&fence);

View File

@ -402,6 +402,8 @@ int drm_release(struct inode *inode, struct file *filp)
current->pid, (long)old_encode_dev(file_priv->minor->device),
dev->open_count);
/* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master) {
if (dev->driver->reclaim_buffers_locked && file_priv->master->lock.hw_lock) {
if (drm_i_have_hw_lock(dev, file_priv)) {
dev->driver->reclaim_buffers_locked(dev, file_priv);
@ -443,6 +445,7 @@ int drm_release(struct inode *inode, struct file *filp)
}
if (drm_i_have_hw_lock(dev, file_priv)) {
DRM_DEBUG("File %p released, freeing lock for context %d\n",
filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
@ -456,6 +459,7 @@ int drm_release(struct inode *inode, struct file *filp)
!dev->driver->reclaim_buffers_locked) {
dev->driver->reclaim_buffers(dev, file_priv);
}
}
drm_fasync(-1, filp, 0);
@ -484,13 +488,15 @@ int drm_release(struct inode *inode, struct file *filp)
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_fb_release(filp);
file_priv->master = NULL;
if (file_priv->is_master) {
drm_put_master(file_priv->minor->master);
if (file_priv->minor->master == file_priv->master)
file_priv->minor->master = NULL;
drm_put_master(file_priv->master);
}
file_priv->master = NULL;
file_priv->is_master = 0;
mutex_lock(&dev->struct_mutex);
drm_object_release(filp);
if (file_priv->remove_auth_on_close == 1) {

View File

@ -90,32 +90,41 @@ static void vblank_disable_fn(unsigned long arg)
static void drm_vblank_cleanup(struct drm_device *dev)
{
/* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0)
return;
del_timer(&dev->vblank_disable_timer);
vblank_disable_fn((unsigned long)dev);
if (dev->vbl_queue)
drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
DRM_MEM_DRIVER);
if (dev->vbl_sigs)
drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
DRM_MEM_DRIVER);
if (dev->_vblank_count)
drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
dev->num_crtcs, DRM_MEM_DRIVER);
if (dev->vblank_refcount)
drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
dev->num_crtcs, DRM_MEM_DRIVER);
if (dev->vblank_enabled)
drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
dev->num_crtcs, DRM_MEM_DRIVER);
if (dev->last_vblank)
drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
DRM_MEM_DRIVER);
if (dev->vblank_premodeset)
drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
dev->num_crtcs, DRM_MEM_DRIVER);
if (dev->vblank_offset)
drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
DRM_MEM_DRIVER);
dev->num_crtcs = 0;
}
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
@ -182,6 +191,82 @@ err:
}
EXPORT_SYMBOL(drm_vblank_init);
int drm_wait_hotplug(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
union drm_wait_hotplug *hotplugwait = data;
struct timeval now;
int ret = 0;
unsigned int flags;
if ((!dev->irq) || (!dev->irq_enabled))
return -EINVAL;
flags = hotplugwait->request.type;
if (flags & _DRM_HOTPLUG_SIGNAL) {
unsigned long irqflags;
struct list_head *hotplug_sigs = dev->hotplug_sigs;
struct drm_hotplug_sig *hotplug_sig;
hotplug_sig = drm_calloc(1, sizeof(struct drm_hotplug_sig),
DRM_MEM_DRIVER);
if (!hotplug_sig)
return -ENOMEM;
atomic_inc(&dev->hotplug_signal_pending);
hotplug_sig->info.si_signo = hotplugwait->request.signal;
hotplug_sig->task = current;
hotplug_sig->counter =
hotplugwait->reply.counter =
dev->mode_config.hotplug_counter;
spin_lock_irqsave(&dev->hotplug_lock, irqflags);
list_add_tail(&hotplug_sig->head, hotplug_sigs);
spin_unlock_irqrestore(&dev->hotplug_lock, irqflags);
} else {
int cur_hotplug = dev->mode_config.hotplug_counter;
DRM_WAIT_ON(ret, dev->hotplug_queue, 3 * DRM_HZ,
dev->mode_config.hotplug_counter > cur_hotplug);
do_gettimeofday(&now);
hotplugwait->reply.tval_sec = now.tv_sec;
hotplugwait->reply.tval_usec = now.tv_usec;
hotplugwait->reply.counter = dev->mode_config.hotplug_counter;
}
return ret;
}
static void drm_hotplug_cleanup(struct drm_device *dev)
{
if (dev->hotplug_sigs)
drm_free(dev->hotplug_sigs, sizeof(*dev->hotplug_sigs),
DRM_MEM_DRIVER);
}
EXPORT_SYMBOL(drm_hotplug_cleanup);
int drm_hotplug_init(struct drm_device *dev)
{
spin_lock_init(&dev->hotplug_lock);
atomic_set(&dev->hotplug_signal_pending, 0);
dev->hotplug_sigs = drm_alloc(sizeof(struct list_head), DRM_MEM_DRIVER);
if (!dev->hotplug_sigs)
return -ENOMEM;
INIT_LIST_HEAD(dev->hotplug_sigs);
init_waitqueue_head(&dev->hotplug_queue);
return 0;
}
EXPORT_SYMBOL(drm_hotplug_init);
/**
* Install IRQ handler.
*
@ -277,6 +362,8 @@ int drm_irq_uninstall(struct drm_device * dev)
drm_vblank_cleanup(dev);
drm_hotplug_cleanup(dev);
dev->locked_tasklet_func = NULL;
return 0;
@ -530,7 +617,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
struct drm_vbl_sig *vbl_sig;
struct drm_vbl_sig *vbl_sig, *tmp;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
@ -538,7 +625,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
* for the same vblank sequence number; nothing to be done in
* that case
*/
list_for_each_entry(vbl_sig, vbl_sigs, head) {
list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
if (vbl_sig->sequence == vblwait->request.sequence
&& vbl_sig->info.si_signo ==
vblwait->request.signal
@ -659,6 +746,53 @@ void drm_handle_vblank(struct drm_device *dev, int crtc)
}
EXPORT_SYMBOL(drm_handle_vblank);
/**
* Send the HOTPLUG signals.
*
* \param dev DRM device.
*
* Sends a signal for each task in drm_device::hotplug_sigs and empties the list.
*/
static void drm_hotplug_send_signals(struct drm_device * dev)
{
struct drm_hotplug_sig *hotplug_sig, *tmp;
struct list_head *hotplug_sigs;
unsigned long flags;
spin_lock_irqsave(&dev->hotplug_lock, flags);
hotplug_sigs = dev->hotplug_sigs;
list_for_each_entry_safe(hotplug_sig, tmp, hotplug_sigs, head) {
hotplug_sig->info.si_code = hotplug_sig->counter;
send_sig_info(hotplug_sig->info.si_signo,
&hotplug_sig->info, hotplug_sig->task);
list_del(&hotplug_sig->head);
drm_free(hotplug_sig, sizeof(*hotplug_sig),
DRM_MEM_DRIVER);
atomic_dec(&dev->hotplug_signal_pending);
}
spin_unlock_irqrestore(&dev->hotplug_lock, flags);
}
/**
* drm_handle_hotplug - handle a hotplug event
* @dev: DRM device
* @crtc: where this event occurred
*
* Drivers should call this routine in their hotplug interrupt handlers.
*/
void drm_handle_hotplug(struct drm_device *dev)
{
DRM_WAKEUP(&dev->hotplug_queue);
drm_hotplug_send_signals(dev);
}
EXPORT_SYMBOL(drm_handle_hotplug);
/**
* Tasklet wrapper function.
*

View File

@ -39,8 +39,10 @@
static struct {
spinlock_t lock;
uint64_t cur_used;
uint64_t emer_used;
uint64_t low_threshold;
uint64_t high_threshold;
uint64_t emer_threshold;
} drm_memctl = {
.lock = SPIN_LOCK_UNLOCKED
};
@ -59,14 +61,30 @@ static inline size_t drm_size_align(size_t size)
int drm_alloc_memctl(size_t size)
{
int ret;
int ret = 0;
unsigned long a_size = drm_size_align(size);
unsigned long new_used = drm_memctl.cur_used + a_size;
spin_lock(&drm_memctl.lock);
ret = ((drm_memctl.cur_used + a_size) > drm_memctl.high_threshold) ?
-ENOMEM : 0;
if (!ret)
if (unlikely(new_used > drm_memctl.high_threshold)) {
if (!DRM_SUSER(DRM_CURPROC) ||
(new_used + drm_memctl.emer_used > drm_memctl.emer_threshold) ||
(a_size > 2*PAGE_SIZE)) {
ret = -ENOMEM;
goto out;
}
/*
* Allow small root-only allocations, even if the
* high threshold is exceeded.
*/
new_used -= drm_memctl.high_threshold;
drm_memctl.emer_used += new_used;
a_size -= new_used;
}
drm_memctl.cur_used += a_size;
out:
spin_unlock(&drm_memctl.lock);
return ret;
}
@ -77,19 +95,30 @@ void drm_free_memctl(size_t size)
unsigned long a_size = drm_size_align(size);
spin_lock(&drm_memctl.lock);
if (likely(a_size >= drm_memctl.emer_used)) {
a_size -= drm_memctl.emer_used;
drm_memctl.emer_used = 0;
} else {
drm_memctl.emer_used -= a_size;
a_size = 0;
}
drm_memctl.cur_used -= a_size;
spin_unlock(&drm_memctl.lock);
}
EXPORT_SYMBOL(drm_free_memctl);
void drm_query_memctl(uint64_t *cur_used,
uint64_t *emer_used,
uint64_t *low_threshold,
uint64_t *high_threshold)
uint64_t *high_threshold,
uint64_t *emer_threshold)
{
spin_lock(&drm_memctl.lock);
*cur_used = drm_memctl.cur_used;
*emer_used = drm_memctl.emer_used;
*low_threshold = drm_memctl.low_threshold;
*high_threshold = drm_memctl.high_threshold;
*emer_threshold = drm_memctl.emer_threshold;
spin_unlock(&drm_memctl.lock);
}
EXPORT_SYMBOL(drm_query_memctl);
@ -99,9 +128,12 @@ void drm_init_memctl(size_t p_low_threshold,
size_t unit_size)
{
spin_lock(&drm_memctl.lock);
drm_memctl.emer_used = 0;
drm_memctl.cur_used = 0;
drm_memctl.low_threshold = p_low_threshold * unit_size;
drm_memctl.high_threshold = p_high_threshold * unit_size;
drm_memctl.emer_threshold = (drm_memctl.high_threshold >> 4) +
drm_memctl.high_threshold;
spin_unlock(&drm_memctl.lock);
}
@ -294,7 +326,12 @@ static void *agp_remap(unsigned long offset, unsigned long size,
return NULL;
}
#endif /* agp */
#else
static void *agp_remap(unsigned long offset, unsigned long size,
struct drm_device * dev)
{
return NULL;
}
#endif /* debug_memory */
void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)

View File

@ -446,9 +446,10 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
struct drm_buffer_manager *bm = &dev->bm;
struct drm_fence_manager *fm = &dev->fm;
uint64_t used_mem;
uint64_t used_emer;
uint64_t low_mem;
uint64_t high_mem;
uint64_t emer_mem;
if (offset > DRM_PROC_LIMIT) {
*eof = 1;
@ -477,7 +478,7 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("Buffer objects are not supported by this driver.\n");
}
drm_query_memctl(&used_mem, &low_mem, &high_mem);
drm_query_memctl(&used_mem, &used_emer, &low_mem, &high_mem, &emer_mem);
if (used_mem > 16*PAGE_SIZE) {
DRM_PROC_PRINT("Used object memory is %lu pages.\n",
@ -486,10 +487,19 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("Used object memory is %lu bytes.\n",
(unsigned long) used_mem);
}
if (used_emer > 16*PAGE_SIZE) {
DRM_PROC_PRINT("Used emergency memory is %lu pages.\n",
(unsigned long) (used_emer >> PAGE_SHIFT));
} else {
DRM_PROC_PRINT("Used emergency memory is %lu bytes.\n\n",
(unsigned long) used_emer);
}
DRM_PROC_PRINT("Soft object memory usage threshold is %lu pages.\n",
(unsigned long) (low_mem >> PAGE_SHIFT));
DRM_PROC_PRINT("Hard object memory usage threshold is %lu pages.\n",
(unsigned long) (high_mem >> PAGE_SHIFT));
DRM_PROC_PRINT("Emergency root only memory usage threshold is %lu pages.\n",
(unsigned long) (emer_mem >> PAGE_SHIFT));
DRM_PROC_PRINT("\n");

View File

@ -88,6 +88,29 @@ again:
return new_id;
}
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
return -EINVAL;
if (!file_priv->master)
return -EINVAL;
if (!file_priv->minor->master && file_priv->minor->master != file_priv->master)
file_priv->minor->master = file_priv->master;
return 0;
}
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
if (!file_priv->master)
return -EINVAL;
file_priv->minor->master = NULL;
return 0;
}
struct drm_master *drm_get_master(struct drm_minor *minor)
{
struct drm_master *master;

View File

@ -299,13 +299,13 @@ int drm_ttm_populate(struct drm_ttm *ttm)
return 0;
be = ttm->be;
if (ttm->page_flags & DRM_TTM_PAGE_WRITE) {
for (i = 0; i < ttm->num_pages; ++i) {
page = drm_ttm_get_page(ttm, i);
if (!page)
return -ENOMEM;
}
}
be->func->populate(be, ttm->num_pages, ttm->pages, ttm->dummy_read_page);
ttm->state = ttm_unbound;
return 0;

View File

@ -120,11 +120,11 @@ static void i915_fence_poll(struct drm_device *dev, uint32_t fence_class,
if (dev_priv->fence_irq_on &&
!(fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
i915_user_irq_off(dev_priv);
i915_user_irq_off(dev);
dev_priv->fence_irq_on = 0;
} else if (!dev_priv->fence_irq_on &&
(fc->waiting_types & DRM_FENCE_TYPE_EXE)) {
i915_user_irq_on(dev_priv);
i915_user_irq_on(dev);
dev_priv->fence_irq_on = 1;
}
}

View File

@ -132,7 +132,7 @@ static void intel_crt_mode_set(struct drm_output *output,
/**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
*
* Only for I945G/GM.
* Not for i915G/i915GM
*
* \return TRUE if CRT is connected.
* \return FALSE if CRT is disconnected.
@ -142,7 +142,7 @@ static bool intel_crt_detect_hotplug(struct drm_output *output)
struct drm_device *dev = output->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 temp;
#if 1
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
temp = I915_READ(PORT_HOTPLUG_EN);
@ -161,15 +161,6 @@ static bool intel_crt_detect_hotplug(struct drm_output *output)
return true;
return false;
#else
temp = I915_READ(PORT_HOTPLUG_STAT);
DRM_DEBUG("HST 0x%08x\n", temp);
if (temp & (1 << 8) && temp & (1 << 9))
return true;
return false;
#endif
}
static bool intel_crt_detect_ddc(struct drm_output *output)
@ -187,7 +178,7 @@ static enum drm_output_status intel_crt_detect(struct drm_output *output)
{
struct drm_device *dev = output->dev;
if (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) {
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
if (intel_crt_detect_hotplug(output))
return output_status_connected;
else

View File

@ -1007,7 +1007,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t control = (pipe == 0) ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
uint32_t base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE;
uint32_t temp;
size_t adder;
size_t addr;
DRM_DEBUG("\n");
@ -1039,17 +1039,21 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOMEM;
}
adder = dev_priv->stolen_base + bo->offset;
intel_crtc->cursor_adder = adder;
if (dev_priv->cursor_needs_physical)
addr = dev_priv->stolen_base + bo->offset;
else
addr = bo->offset;
intel_crtc->cursor_addr = addr;
temp = 0;
/* set the pipe for the cursor */
temp |= (pipe << 28);
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
DRM_DEBUG("cusror base %x\n", adder);
DRM_DEBUG("cusror base %x\n", addr);
I915_WRITE(control, temp);
I915_WRITE(base, adder);
I915_WRITE(base, addr);
return 0;
}
@ -1075,7 +1079,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
adder = intel_crtc->cursor_adder;
adder = intel_crtc->cursor_addr;
I915_WRITE((pipe == 0) ? CURSOR_A_POSITION : CURSOR_B_POSITION, temp);
I915_WRITE((pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE, adder);
@ -1241,7 +1245,7 @@ void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc->lut_b[i] = i;
}
intel_crtc->cursor_adder = 0;
intel_crtc->cursor_addr = 0;
crtc->driver_private = intel_crtc;
}

View File

@ -56,7 +56,7 @@ struct intel_output {
struct intel_crtc {
int pipe;
int plane;
uint32_t cursor_adder;
uint32_t cursor_addr;
u8 lut_r[256], lut_g[256], lut_b[256];
};

View File

@ -157,7 +157,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
break;
case 16:
var->red.offset = 11;
var->green.offset = 6;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;

View File

@ -53,7 +53,6 @@ struct intel_sdvo_priv {
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
struct intel_sdvo_dtd save_output_dtd[16];
u32 save_SDVOX;
int hotplug_enabled;
};
/**
@ -72,14 +71,8 @@ void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
if (sdvo_priv->output_device == SDVOB) {
cval = I915_READ(SDVOC);
if (sdvo_priv->hotplug_enabled)
bval = bval | (1 << 26);
} else {
bval = I915_READ(SDVOB);
if (sdvo_priv->hotplug_enabled)
cval = cval | (1 << 26);
}
/*
* Write the registers twice for luck. Sometimes,
@ -933,8 +926,6 @@ int intel_sdvo_supports_hotplug(struct drm_output *output)
void intel_sdvo_set_hotplug(struct drm_output *output, int on)
{
struct intel_output *intel_output = output->driver_private;
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u8 response[2];
u8 status;
@ -942,15 +933,11 @@ void intel_sdvo_set_hotplug(struct drm_output *output, int on)
intel_sdvo_read_response(output, &response, 2);
if (on) {
sdvo_priv->hotplug_enabled = 1;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(output, &response, 2);
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
} else {
sdvo_priv->hotplug_enabled = 0;
response[0] = 0;
response[1] = 0;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
@ -1074,7 +1061,6 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
}
sdvo_priv->output_device = output_device;
sdvo_priv->hotplug_enabled = 0;
intel_output->i2c_bus = i2cbus;
intel_output->dev_priv = sdvo_priv;

View File

@ -555,6 +555,39 @@ union drm_wait_vblank {
struct drm_wait_vblank_reply reply;
};
/* Handle monitor hotplug.
*
* May want to extend this later to pass reply information which
* details the outputs which generated the hotplug event.
* Some chipsets can't determine that though, and we'd need to leave
* it to the higher levels to determine exactly what changed.
*/
enum drm_hotplug_seq_type {
_DRM_HOTPLUG_SIGNAL = 0x00000001, /**< Send signal instead of blocking */
};
struct drm_wait_hotplug_request {
enum drm_hotplug_seq_type type;
unsigned long signal;
};
struct drm_wait_hotplug_reply {
enum drm_hotplug_seq_type type;
unsigned int counter;
long tval_sec;
long tval_usec;
};
/**
* DRM_IOCTL_WAIT_HOTPLUG ioctl argument type.
*
* \sa drmWaitHotplug().
*/
union drm_wait_hotplug {
struct drm_wait_hotplug_request request;
struct drm_wait_hotplug_reply reply;
};
enum drm_modeset_ctl_cmd {
_DRM_PRE_MODESET = 1,
_DRM_POST_MODESET = 2,
@ -1167,6 +1200,9 @@ struct drm_mode_hotplug {
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
@ -1238,6 +1274,7 @@ struct drm_mode_hotplug {
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property)
#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xAC, struct drm_mode_cursor)
#define DRM_IOCTL_MODE_HOTPLUG DRM_IOWR(0xAD, struct drm_mode_hotplug)
#define DRM_IOCTL_WAIT_HOTPLUG DRM_IOWR(0xAE, union drm_wait_hotplug)
/*@}*/

View File

@ -1180,7 +1180,6 @@ static int i915_handle_copyback(struct drm_device *dev,
buffers++;
}
}
return err;
}
@ -1272,7 +1271,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
int num_buffers;
int ret;
struct drm_i915_validate_buffer *buffers;
if (!dev_priv->allow_batchbuffer) {
DRM_ERROR("Batchbuffer ioctl disabled\n");
@ -1288,7 +1286,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
return -EINVAL;
ret = drm_bo_read_lock(&dev->bm.bm_lock);
if (ret)
return ret;
@ -1306,8 +1303,12 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
num_buffers = exec_buf->num_buffers;
buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), DRM_MEM_DRIVER);
if (!buffers) {
if (!dev_priv->val_bufs) {
dev_priv->val_bufs =
vmalloc(sizeof(struct drm_i915_validate_buffer)*
dev_priv->max_validate_buffers);
}
if (!dev_priv->val_bufs) {
drm_bo_read_unlock(&dev->bm.bm_lock);
mutex_unlock(&dev_priv->cmdbuf_mutex);
return -ENOMEM;
@ -1315,7 +1316,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
/* validate buffer list + fixup relocations */
ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
buffers, &num_buffers);
dev_priv->val_bufs, &num_buffers);
if (ret)
goto out_err0;
@ -1324,7 +1325,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
drm_agp_chipset_flush(dev);
/* submit buffer */
batch->start = buffers[num_buffers-1].buffer->offset;
batch->start = dev_priv->val_bufs[num_buffers-1].buffer->offset;
DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
batch->start, batch->used, batch->num_cliprects);
@ -1341,13 +1342,11 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
out_err0:
/* handle errors */
ret = i915_handle_copyback(dev, buffers, num_buffers, ret);
ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret);
mutex_lock(&dev->struct_mutex);
i915_dereference_buffers_locked(buffers, num_buffers);
i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers);
mutex_unlock(&dev->struct_mutex);
drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER);
mutex_unlock(&dev_priv->cmdbuf_mutex);
drm_bo_read_unlock(&dev->bm.bm_lock);
return ret;

View File

@ -69,6 +69,7 @@
#ifdef I915_HAVE_BUFFER
#define I915_MAX_VALIDATE_BUFFERS 4096
struct drm_i915_validate_buffer;
#endif
struct drm_i915_ring_buffer {
@ -139,9 +140,10 @@ struct drm_i915_private {
int fence_irq_on;
uint32_t irq_enable_reg;
int irq_enabled;
struct workqueue_struct *wq;
bool cursor_needs_physical;
#ifdef I915_HAVE_FENCE
uint32_t flush_sequence;
uint32_t flush_flags;
@ -153,6 +155,7 @@ struct drm_i915_private {
unsigned int max_validate_buffers;
struct mutex cmdbuf_mutex;
size_t stolen_base;
struct drm_i915_validate_buffer *val_bufs;
#endif
DRM_SPINTYPE swaps_lock;
@ -306,8 +309,8 @@ extern void i915_disable_vblank(struct drm_device *dev, int crtc);
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_user_irq_on(struct drm_i915_private *dev_priv);
extern void i915_user_irq_off(struct drm_i915_private *dev_priv);
extern void i915_user_irq_on(struct drm_device *dev);
extern void i915_user_irq_off(struct drm_device *dev);
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
@ -519,10 +522,23 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/* Interrupt bits:
*/
#define USER_INT_FLAG (1<<1)
#define VSYNC_PIPEB_FLAG (1<<5)
#define VSYNC_PIPEA_FLAG (1<<7)
#define HWB_OOM_FLAG (1<<13) /* binner out of memory */
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
#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_INT_IDENTITY_R 0x020a4
@ -535,6 +551,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define I915REG_PIPEASTAT 0x70024
#define I915REG_PIPEBSTAT 0x71024
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
#define I915_HOTPLUG_INTERRUPT_ENABLE (1UL<<26)
#define I915_HOTPLUG_CLEAR (1UL<<10)
#define I915_VBLANK_CLEAR (1UL<<1)
/*
* The two pipe frame counter registers are not synchronized, so
* reading a stable value is somewhat tricky. The following code
@ -566,9 +588,6 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define PIPE_PIXEL_MASK 0x00ffffff
#define PIPE_PIXEL_SHIFT 0
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
#define I915_VBLANK_CLEAR (1UL<<1)
#define GPIOA 0x5010
#define GPIOB 0x5014
#define GPIOC 0x5018
@ -626,6 +645,34 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define VCO_LOOP_DIV_BY_4M 0x00
#define VCO_LOOP_DIV_BY_16M 0x04
#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_HOTPLUG_INTERRUPT_ENABLE (1UL<<26)
#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_HOTPLUG_INTERRUPT_STATUS (1UL<<10)
#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_DATA 0x3c5
#define SR01 1
@ -1152,8 +1199,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define SDVOB_PCIE_CONCURRENCY (1 << 3)
#define SDVO_DETECTED (1 << 2)
/* Bits to be preserved when writing */
#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
#define SDVOC_PRESERVE_MASK (1 << 17)
#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
#define SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
/** @defgroup LVDS
* @{

View File

@ -130,6 +130,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
if (IS_MOBILE(dev) || IS_I9XX(dev))
dev_priv->cursor_needs_physical = true;
else
dev_priv->cursor_needs_physical = false;
if (IS_I965G(dev) || IS_G33(dev))
dev_priv->cursor_needs_physical = false;
if (IS_I9XX(dev)) {
pci_read_config_dword(dev->pdev, 0x5C, &dev_priv->stolen_base);
DRM_DEBUG("stolen base %p\n", (void*)dev_priv->stolen_base);
@ -269,7 +277,6 @@ int i915_driver_unload(struct drm_device *dev)
I915_WRITE(LP_RING + RING_LEN, 0);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_irq_uninstall(dev);
intel_modeset_cleanup(dev);
@ -283,7 +290,6 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->sarea_kmap.virtual) {
drm_bo_kunmap(&dev_priv->sarea_kmap);
dev_priv->sarea_kmap.virtual = NULL;
dev->primary->master->lock.hw_lock = NULL;
dev->sigdata.lock = NULL;
}
@ -377,7 +383,9 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
if (!master_priv)
return;
if (master_priv->sarea)
drm_rmmap(dev, master_priv->sarea);
drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
master->driver_priv = NULL;

View File

@ -30,14 +30,8 @@
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "intel_drv.h"
#define USER_INT_FLAG (1<<1)
#define VSYNC_PIPEB_FLAG (1<<5)
#define VSYNC_PIPEA_FLAG (1<<7)
#define HOTPLUG_FLAG (1 << 17)
#define MAX_NOPID ((u32)~0)
/**
@ -158,13 +152,14 @@ static void i915_vblank_tasklet(struct drm_device *dev)
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
unsigned counter[2];
struct drm_drawable_info *drw;
struct drm_i915_sarea *sarea_priv;
struct drm_i915_sarea *sarea_priv = master_priv->sarea_priv;
u32 cpp = dev_priv->cpp, offsets[3];
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB)
: XY_SRC_COPY_BLT_CMD;
u32 pitchropcpp;
u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
(cpp << 23) | (1 << 24);
RING_LOCALS;
counter[0] = drm_vblank_count(dev, 0);
@ -434,7 +429,7 @@ static struct drm_device *hotplug_dev;
static int hotplug_cmd = 0;
static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
static void i915_hotplug_crt(struct drm_device *dev, bool connected)
static void i915_hotplug_crt(struct drm_device *dev, bool isconnected)
{
struct drm_output *output;
struct intel_output *iout;
@ -453,7 +448,7 @@ static void i915_hotplug_crt(struct drm_device *dev, bool connected)
if (iout == 0)
goto unlock;
drm_hotplug_stage_two(dev, output, connected);
drm_hotplug_stage_two(dev, output, isconnected);
unlock:
mutex_unlock(&dev->mode_config.mutex);
@ -468,10 +463,8 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
output = intel_sdvo_find(dev, sdvoB);
if (!output) {
DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C");
if (!output)
goto unlock;
}
status = output->funcs->detect(output);
@ -480,7 +473,6 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
else
drm_hotplug_stage_two(dev, output, true);
/* wierd hw bug, sdvo stop sending interupts */
intel_sdvo_set_hotplug(output, 1);
unlock:
@ -521,6 +513,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
if (sdvoC)
i915_hotplug_sdvo(dev, 0);
drm_handle_hotplug(dev);
}
static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)
@ -574,100 +567,104 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
struct drm_device *dev = (struct drm_device *) arg;
struct drm_i915_master_private *master_priv;
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
u32 temp = 0;
u32 temp2;
u32 iir;
u32 pipea_stats, pipeb_stats;
int hotplug = 0;
int vblank = 0;
pipea_stats = I915_READ(I915REG_PIPEASTAT);
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
/* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */
if (IS_I9XX(dev))
temp = I915_READ(I915REG_INT_IDENTITY_R);
/* 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(I915REG_INT_IDENTITY_R);
else
temp = I915_READ16(I915REG_INT_IDENTITY_R);
iir = I915_READ16(I915REG_INT_IDENTITY_R);
temp2 = temp;
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
iir &= (dev_priv->irq_enable_reg | I915_USER_INTERRUPT);
#if 0
/* ugly despamification of pipeb event irq */
if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) {
DRM_DEBUG("IIR %08x\n", temp2);
DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG);
DRM_DEBUG("M&I %08x\n", temp);
DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT));
}
#else
#if 0
DRM_DEBUG("flag=%08x\n", temp);
DRM_DEBUG("flag=%08x\n", iir);
#endif
#endif
if (temp == 0)
if (iir == 0) {
DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
iir,
I915_READ(I915REG_INT_MASK_R),
I915_READ(I915REG_INT_ENABLE_R),
I915_READ(I915REG_PIPEASTAT),
I915_READ(I915REG_PIPEBSTAT));
return IRQ_NONE;
if (IS_I9XX(dev)) {
I915_WRITE(I915REG_INT_IDENTITY_R, temp);
(void) I915_READ(I915REG_INT_IDENTITY_R);
} else {
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
(void) I915_READ16(I915REG_INT_IDENTITY_R);
}
/*
* Clear the PIPE(A|B)STAT regs before the IIR otherwise
* we may get extra interrupts.
*/
if (temp & VSYNC_PIPEA_FLAG) {
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
pipea_stats = I915_READ(I915REG_PIPEASTAT);
if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
I915_VBLANK_INTERRUPT_STATUS))
{
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 0));
I915_WRITE(I915REG_PIPEASTAT,
pipea_stats | I915_VBLANK_INTERRUPT_ENABLE |
I915_VBLANK_CLEAR);
}
if (temp & VSYNC_PIPEB_FLAG) {
/* This is a global event, and not a pipe A event */
if (pipea_stats & I915_HOTPLUG_INTERRUPT_STATUS)
hotplug = 1;
I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
}
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
I915_VBLANK_INTERRUPT_STATUS))
{
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 1));
I915_WRITE(I915REG_PIPEBSTAT,
pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE |
I915_VBLANK_CLEAR);
}
I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
}
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
(void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
DRM_READMEMORYBARRIER();
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
VSYNC_PIPEB_FLAG);
/* Clear the generated interrupt */
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
I915_WRITE(I915REG_INT_IDENTITY_R, iir);
(void) I915_READ(I915REG_INT_IDENTITY_R);
} else {
I915_WRITE16(I915REG_INT_IDENTITY_R, iir);
(void) I915_READ16(I915REG_INT_IDENTITY_R);
}
if (dev->primary->master) {
master_priv = dev->primary->master->driver_priv;
master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
}
if (temp & USER_INT_FLAG) {
if (iir & I915_USER_INTERRUPT) {
DRM_WAKEUP(&dev_priv->irq_queue);
#ifdef I915_HAVE_FENCE
i915_fence_handler(dev);
#endif
}
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
if (vblank) {
if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet);
}
/* for now lest just ack it */
if (temp & (1 << 17)) {
DRM_DEBUG("Hotplug event received\n");
if ((iir & I915_DISPLAY_PORT_INTERRUPT) || hotplug) {
u32 temp2 = 0;
DRM_INFO("Hotplug event received\n");
if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev)) {
temp2 |= SDVOB_HOTPLUG_INT_STATUS |
SDVOC_HOTPLUG_INT_STATUS;
} else {
temp2 = I915_READ(PORT_HOTPLUG_STAT);
i915_run_hotplug_tasklet(dev, temp2);
I915_WRITE(PORT_HOTPLUG_STAT, temp2);
}
i915_run_hotplug_tasklet(dev, temp2);
}
return IRQ_HANDLED;
}
@ -691,22 +688,32 @@ int i915_emit_irq(struct drm_device *dev)
return dev_priv->counter;
}
void i915_user_irq_on(struct drm_i915_private *dev_priv)
void i915_user_irq_on(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
dev_priv->irq_enable_reg |= USER_INT_FLAG;
dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
else
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
}
DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
}
void i915_user_irq_off(struct drm_i915_private *dev_priv)
void i915_user_irq_off(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
// dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
// dev_priv->irq_enable_reg &= ~I915_USER_INTERRUPT;
// if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
// I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
// else
// I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
}
DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
@ -725,10 +732,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
if (READ_BREADCRUMB(dev_priv) >= irq_nr)
return 0;
i915_user_irq_on(dev_priv);
i915_user_irq_on(dev);
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
READ_BREADCRUMB(dev_priv) >= irq_nr);
i915_user_irq_off(dev_priv);
i915_user_irq_off(dev);
if (ret == -EBUSY) {
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
@ -789,13 +796,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int pipe = i915_get_pipe(dev, plane);
u32 pipestat_reg = 0;
u32 pipestat;
switch (pipe) {
case 0:
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
pipestat_reg = I915REG_PIPEASTAT;
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
break;
case 1:
dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
pipestat_reg = I915REG_PIPEBSTAT;
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
break;
default:
DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
@ -803,8 +814,31 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
break;
}
if (pipestat_reg)
{
pipestat = I915_READ (pipestat_reg);
/*
* Older chips didn't have the start vblank interrupt,
* but
*/
if (IS_I965G (dev))
pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
else
pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
/*
* Clear any pending status
*/
pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
I915_VBLANK_INTERRUPT_STATUS);
I915_WRITE(pipestat_reg, pipestat);
}
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
else
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
return 0;
}
@ -812,13 +846,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int pipe = i915_get_pipe(dev, plane);
u32 pipestat_reg = 0;
u32 pipestat;
switch (pipe) {
case 0:
dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
pipestat_reg = I915REG_PIPEASTAT;
dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
break;
case 1:
dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG;
pipestat_reg = I915REG_PIPEBSTAT;
dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
break;
default:
DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
@ -826,7 +864,23 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
break;
}
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
else
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
if (pipestat_reg)
{
pipestat = I915_READ (pipestat_reg);
pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
I915_VBLANK_INTERRUPT_ENABLE);
/*
* Clear any pending status
*/
pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
I915_VBLANK_INTERRUPT_STATUS);
I915_WRITE(pipestat_reg, pipestat);
}
}
void i915_enable_interrupt (struct drm_device *dev)
@ -834,42 +888,64 @@ void i915_enable_interrupt (struct drm_device *dev)
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
struct drm_output *o;
dev_priv->irq_enable_reg |= USER_INT_FLAG;
dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
if (IS_I9XX(dev) && dev->mode_config.num_output) {
dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
if (dev->mode_config.num_output)
dev_priv->irq_enable_reg |= I915_DISPLAY_PORT_INTERRUPT;
} else {
if (dev->mode_config.num_output)
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
/* Enable global interrupts for hotplug - not a pipeA event */
I915_WRITE(I915REG_PIPEASTAT, I915_READ(I915REG_PIPEASTAT) | I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR);
}
if (dev_priv->irq_enable_reg & (I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) {
u32 temp = 0;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
temp = I915_READ(PORT_HOTPLUG_EN);
/* Activate the CRT */
I915_WRITE(PORT_HOTPLUG_EN, CRT_HOTPLUG_INT_EN);
temp |= CRT_HOTPLUG_INT_EN;
}
if (IS_I9XX(dev)) {
/* SDVOB */
o = intel_sdvo_find(dev, 1);
if (o && intel_sdvo_supports_hotplug(o)) {
intel_sdvo_set_hotplug(o, 1);
I915_WRITE(PORT_HOTPLUG_EN, SDVOB_HOTPLUG_INT_EN);
temp |= SDVOB_HOTPLUG_INT_EN;
}
/* SDVOC */
o = intel_sdvo_find(dev, 0);
if (o && intel_sdvo_supports_hotplug(o)) {
intel_sdvo_set_hotplug(o, 1);
I915_WRITE(PORT_HOTPLUG_EN, SDVOC_HOTPLUG_INT_EN);
temp |= SDVOC_HOTPLUG_INT_EN;
}
}
if (IS_I9XX(dev)) {
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
I915_WRITE(SDVOB, I915_READ(SDVOB) | SDVO_INTERRUPT_ENABLE);
I915_WRITE(SDVOC, I915_READ(SDVOC) | SDVO_INTERRUPT_ENABLE);
} else {
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
/* DVO ???? */
}
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
I915_WRITE(PORT_HOTPLUG_EN, temp);
DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R));
DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB));
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
}
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
else
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
dev_priv->irq_enabled = 1;
}
@ -909,11 +985,15 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
return -EINVAL;
}
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev))
flag = I915_READ(I915REG_INT_ENABLE_R);
else
flag = I915_READ16(I915REG_INT_ENABLE_R);
pipe->pipe = 0;
if (flag & VSYNC_PIPEA_FLAG)
if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
if (flag & VSYNC_PIPEB_FLAG)
if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
return 0;
@ -1087,7 +1167,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
I915_WRITE16(I915REG_HWSTAM, 0xeffe);
if (IS_I9XX(dev)) {
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
I915_WRITE(I915REG_INT_MASK_R, 0x0);
I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
} else {
@ -1114,6 +1194,10 @@ int i915_driver_irq_postinstall(struct drm_device * dev)
if (ret)
return ret;
ret = drm_hotplug_init(dev);
if (ret)
return ret;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
i915_enable_interrupt(dev);
@ -1137,8 +1221,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
dev_priv->irq_enabled = 0;
if(IS_I9XX(dev)) {
temp = I915_READ(I915REG_PIPEASTAT);
I915_WRITE(I915REG_PIPEASTAT, temp);
temp = I915_READ(I915REG_PIPEBSTAT);
I915_WRITE(I915REG_PIPEBSTAT, temp);
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
I915_WRITE(I915REG_HWSTAM, 0xffffffff);
I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
I915_WRITE(I915REG_INT_ENABLE_R, 0x0);

View File

@ -390,6 +390,34 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
return 0;
}
static int
nouveau_channel_idle(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine = &dev_priv->Engine;
uint32_t caches;
int idle;
caches = NV_READ(NV03_PFIFO_CACHES);
NV_WRITE(NV03_PFIFO_CACHES, caches & ~1);
if (engine->fifo.channel_id(dev) != chan->id) {
struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
if (INSTANCE_RD(ramfc, 0) != INSTANCE_RD(ramfc, 1))
idle = 0;
else
idle = 1;
} else {
idle = (NV_READ(NV04_PFIFO_CACHE1_DMA_GET) ==
NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
}
NV_WRITE(NV03_PFIFO_CACHES, caches);
return idle;
}
/* stops a fifo */
void nouveau_fifo_free(struct nouveau_channel *chan)
{
@ -400,22 +428,9 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
/* Disable channel switching, if this channel isn't currenly
* active re-enable it if there's still pending commands.
* We really should do a manual context switch here, but I'm
* not sure I trust our ability to do this reliably yet..
*/
NV_WRITE(NV03_PFIFO_CACHES, 0);
if (engine->fifo.channel_id(dev) != chan->id &&
NV_READ(chan->get) != NV_READ(chan->put)) {
NV_WRITE(NV03_PFIFO_CACHES, 1);
}
/* Give the channel a chance to idle, wait 2s (hopefully) */
t_start = engine->timer.read(dev);
while (NV_READ(chan->get) != NV_READ(chan->put) ||
NV_READ(NV03_PFIFO_CACHE1_GET) !=
NV_READ(NV03_PFIFO_CACHE1_PUT)) {
while (!nouveau_channel_idle(chan)) {
if (engine->timer.read(dev) - t_start > 2000000000ULL) {
DRM_ERROR("Failed to idle channel %d before destroy."
"Prepare for strangeness..\n", chan->id);
@ -433,13 +448,6 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
/* stop the fifo, otherwise it could be running and
* it will crash when removing gpu objects
*XXX: from real-world evidence, absolutely useless..
*/
NV_WRITE(chan->get, chan->pushbuf_base);
NV_WRITE(chan->put, chan->pushbuf_base);
// FIXME XXX needs more code
engine->fifo.destroy_context(chan);

View File

@ -300,6 +300,32 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
return 0;
}
static void nouveau_mem_reset_agp(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1);
saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19);
/* clear busmaster bit */
NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
/* clear SBA and AGP bits */
NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
/* power cycle pgraph, if enabled */
pmc_enable = NV_READ(NV03_PMC_ENABLE);
if (pmc_enable & NV_PMC_ENABLE_PGRAPH) {
NV_WRITE(NV03_PMC_ENABLE, pmc_enable & ~NV_PMC_ENABLE_PGRAPH);
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
NV_PMC_ENABLE_PGRAPH);
}
/* and restore (gives effect of resetting AGP) */
NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
}
static int
nouveau_mem_init_agp(struct drm_device *dev, int ttm)
{
@ -308,6 +334,8 @@ nouveau_mem_init_agp(struct drm_device *dev, int ttm)
struct drm_agp_mode mode;
int ret;
nouveau_mem_reset_agp(dev);
ret = drm_agp_acquire(dev);
if (ret) {
DRM_ERROR("Unable to acquire AGP: %d\n", ret);

View File

@ -7,25 +7,12 @@ int
nv04_mc_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t saved_pci_nv_1, saved_pci_nv_19;
saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1);
saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19);
/* clear busmaster bit */
NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~(0x00000001 << 2));
/* clear SBA and AGP bits */
NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
/* Power up everything, resetting each individual unit will
* be done later if needed.
*/
NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
/* and restore (gives effect of resetting AGP) */
NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
return 0;
}

View File

@ -3126,11 +3126,13 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil
DRM_DEBUG("color tiling disabled\n");
dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->tiling_enabled = 0;
} else if (sp->value == 1) {
DRM_DEBUG("color tiling enabled\n");
dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->tiling_enabled = 1;
}
break;

View File

@ -22,6 +22,7 @@
#include <sys/ioctl.h>
#include <linux/fb.h>
#endif
#include <signal.h>
#include "xf86drm.h"
#include "xf86drmMode.h"
@ -387,9 +388,28 @@ drmModeCrtcPtr demoFindFreeCrtc(struct demo_driver *driver, drmModeOutputPtr out
return crtc;
}
static int driverfd;
static void
hotplugSIGNAL(int sig, siginfo_t *si, void *d)
{
union drm_wait_hotplug hw;
int ret;
printf("GOT HOTPLUG EVENT!\n");
/* ask for another hotplug event ! */
memset(&hw, 0, sizeof(hw));
hw.request.type = _DRM_HOTPLUG_SIGNAL;
hw.request.signal = SIGUSR1;
ret = ioctl(driverfd, DRM_IOCTL_WAIT_HOTPLUG, &hw);
}
struct demo_driver* demoCreateDriver(void)
{
struct demo_driver* driver = malloc(sizeof(struct demo_driver));
union drm_wait_hotplug hw;
int ret = 0;
memset(driver, 0, sizeof(struct demo_driver));
@ -400,6 +420,33 @@ struct demo_driver* demoCreateDriver(void)
goto err_driver;
}
#if 0
/* ioctl wait for hotplug */
do {
memset(&hw, 0, sizeof(hw));
ret = ioctl(driver->fd, DRM_IOCTL_WAIT_HOTPLUG, &hw);
printf("HOTPLUG %d %d %d\n",ret,errno,hw.reply.counter);
} while (ret && errno == EBUSY);
#else
/* signal for hotplug */
{
struct sigaction sa;
struct sigaction osa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = hotplugSIGNAL;
sigaction(SIGUSR1, &sa, &osa);
driverfd = driver->fd;
memset(&hw, 0, sizeof(hw));
hw.request.type = _DRM_HOTPLUG_SIGNAL;
hw.request.signal = SIGUSR1;
ret = ioctl(driver->fd, DRM_IOCTL_WAIT_HOTPLUG, &hw);
}
#endif
demoUpdateRes(driver);
if (!driver->res) {
printf("could not retrive resources\n");