Merge branch 'modesetting-101' of ssh://git.freedesktop.org/git/mesa/drm into modesetting-101
commit
71b66b0043
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
* @{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue