mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-03 04:28:01 +02:00
Merge remote branch 'origin/master' into modesetting-101
Conflicts: linux-core/drm_bo.c linux-core/drm_drv.c shared-core/drm.h shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c shared-core/radeon_irq.c
This commit is contained in:
commit
e7a41d7f5b
77 changed files with 2411 additions and 1264 deletions
|
|
@ -2585,7 +2585,7 @@ static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf)
|
|||
buf->size = rep->size;
|
||||
buf->offset = rep->offset;
|
||||
buf->mapHandle = rep->arg_handle;
|
||||
buf->mask = rep->mask;
|
||||
buf->proposedFlags = rep->proposed_flags;
|
||||
buf->start = rep->buffer_start;
|
||||
buf->fenceFlags = rep->fence_flags;
|
||||
buf->replyFlags = rep->rep_flags;
|
||||
|
|
@ -2599,7 +2599,7 @@ static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf)
|
|||
|
||||
int drmBOCreate(int fd, unsigned long size,
|
||||
unsigned pageAlignment, void *user_buffer,
|
||||
uint64_t mask,
|
||||
uint64_t flags,
|
||||
unsigned hint, drmBO *buf)
|
||||
{
|
||||
struct drm_bo_create_arg arg;
|
||||
|
|
@ -2609,7 +2609,7 @@ int drmBOCreate(int fd, unsigned long size,
|
|||
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
req->mask = mask;
|
||||
req->flags = flags;
|
||||
req->hint = hint;
|
||||
req->size = size;
|
||||
req->page_alignment = pageAlignment;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ typedef struct _drmBO
|
|||
unsigned handle;
|
||||
uint64_t mapHandle;
|
||||
uint64_t flags;
|
||||
uint64_t mask;
|
||||
uint64_t proposedFlags;
|
||||
unsigned mapFlags;
|
||||
unsigned long size;
|
||||
unsigned long offset;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ static void *drm_ati_alloc_pcigart_table(int order)
|
|||
struct page *page;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order);
|
||||
DRM_DEBUG("%d order\n", order);
|
||||
|
||||
address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
|
||||
order);
|
||||
|
|
@ -97,7 +97,7 @@ static void *drm_ati_alloc_pcigart_table(int order)
|
|||
SetPageReserved(page);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
|
||||
DRM_DEBUG("returning 0x%08lx\n", address);
|
||||
return (void *)address;
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ static void drm_ati_free_pcigart_table(void *address, int order)
|
|||
struct page *page;
|
||||
int i;
|
||||
int num_pages = 1 << order;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
page = virt_to_page((unsigned long)address);
|
||||
|
||||
|
|
|
|||
|
|
@ -104,10 +104,8 @@ struct drm_file;
|
|||
#define DRIVER_HAVE_DMA 0x20
|
||||
#define DRIVER_HAVE_IRQ 0x40
|
||||
#define DRIVER_IRQ_SHARED 0x80
|
||||
#define DRIVER_IRQ_VBL 0x100
|
||||
#define DRIVER_DMA_QUEUE 0x200
|
||||
#define DRIVER_FB_DMA 0x400
|
||||
#define DRIVER_IRQ_VBL2 0x800
|
||||
#define DRIVER_DMA_QUEUE 0x100
|
||||
#define DRIVER_FB_DMA 0x200
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -632,9 +630,51 @@ struct drm_driver {
|
|||
int (*context_dtor) (struct drm_device *dev, int context);
|
||||
int (*kernel_context_switch) (struct drm_device *dev, int old,
|
||||
int new);
|
||||
void (*kernel_context_switch_unlock) (struct drm_device *dev);
|
||||
int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
|
||||
int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
|
||||
void (*kernel_context_switch_unlock) (struct drm_device * dev);
|
||||
/**
|
||||
* get_vblank_counter - get raw hardware vblank counter
|
||||
* @dev: DRM device
|
||||
* @crtc: counter to fetch
|
||||
*
|
||||
* Driver callback for fetching a raw hardware vblank counter
|
||||
* for @crtc. If a device doesn't have a hardware counter, the
|
||||
* driver can simply return the value of drm_vblank_count and
|
||||
* make the enable_vblank() and disable_vblank() hooks into no-ops,
|
||||
* leaving interrupts enabled at all times.
|
||||
*
|
||||
* Wraparound handling and loss of events due to modesetting is dealt
|
||||
* with in the DRM core code.
|
||||
*
|
||||
* RETURNS
|
||||
* Raw vblank counter value.
|
||||
*/
|
||||
u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
|
||||
|
||||
/**
|
||||
* enable_vblank - enable vblank interrupt events
|
||||
* @dev: DRM device
|
||||
* @crtc: which irq to enable
|
||||
*
|
||||
* Enable vblank interrupts for @crtc. If the device doesn't have
|
||||
* a hardware vblank counter, this routine should be a no-op, since
|
||||
* interrupts will have to stay on to keep the count accurate.
|
||||
*
|
||||
* RETURNS
|
||||
* Zero on success, appropriate errno if the given @crtc's vblank
|
||||
* interrupt cannot be enabled.
|
||||
*/
|
||||
int (*enable_vblank) (struct drm_device *dev, int crtc);
|
||||
|
||||
/**
|
||||
* disable_vblank - disable vblank interrupt events
|
||||
* @dev: DRM device
|
||||
* @crtc: which irq to enable
|
||||
*
|
||||
* Disable vblank interrupts for @crtc. If the device doesn't have
|
||||
* a hardware vblank counter, this routine should be a no-op, since
|
||||
* interrupts will have to stay on to keep the count accurate.
|
||||
*/
|
||||
void (*disable_vblank) (struct drm_device *dev, int crtc);
|
||||
int (*dri_library_name) (struct drm_device *dev, char * buf);
|
||||
|
||||
/**
|
||||
|
|
@ -653,7 +693,7 @@ struct drm_driver {
|
|||
/* these have to be filled in */
|
||||
irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
|
||||
void (*irq_preinstall) (struct drm_device *dev);
|
||||
void (*irq_postinstall) (struct drm_device *dev);
|
||||
int (*irq_postinstall) (struct drm_device *dev);
|
||||
void (*irq_uninstall) (struct drm_device *dev);
|
||||
void (*reclaim_buffers) (struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
|
|
@ -799,13 +839,19 @@ struct drm_device {
|
|||
/** \name VBLANK IRQ support */
|
||||
/*@{ */
|
||||
|
||||
wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
|
||||
atomic_t vbl_received;
|
||||
atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
|
||||
wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */
|
||||
atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
|
||||
spinlock_t vbl_lock;
|
||||
struct list_head vbl_sigs; /**< signal list to send on VBLANK */
|
||||
struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
|
||||
unsigned int vbl_pending;
|
||||
struct list_head *vbl_sigs; /**< signal list to send on VBLANK */
|
||||
atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/
|
||||
atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */
|
||||
u32 *last_vblank; /* protected by dev->vbl_lock, used */
|
||||
/* for wraparound handling */
|
||||
u32 *vblank_offset; /* used to track how many vblanks */
|
||||
u32 *vblank_premodeset; /* were lost during modeset */
|
||||
struct timer_list vblank_disable_timer;
|
||||
|
||||
unsigned long max_vblank_count; /**< size of vblank counter register */
|
||||
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
|
||||
void (*locked_tasklet_func)(struct drm_device *dev);
|
||||
|
||||
|
|
@ -825,6 +871,7 @@ struct drm_device {
|
|||
#ifdef __alpha__
|
||||
struct pci_controller *hose;
|
||||
#endif
|
||||
int num_crtcs; /**< Number of CRTCs on this device */
|
||||
struct drm_sg_mem *sg; /**< Scatter gather memory */
|
||||
void *dev_private; /**< device private data */
|
||||
struct drm_sigdata sigdata; /**< For block_all_signals */
|
||||
|
|
@ -1113,11 +1160,19 @@ 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_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
|
||||
extern void drm_vbl_send_signals(struct drm_device *dev);
|
||||
extern 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_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
|
||||
extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
|
||||
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
|
||||
extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
|
||||
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
|
||||
extern int drm_vblank_get(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||
|
||||
/* Modesetting support */
|
||||
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* AGP/GART support (drm_agpsupport.h) */
|
||||
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
|
||||
|
|
|
|||
|
|
@ -505,12 +505,14 @@ static int drm_agp_needs_unbind_cache_adjust(struct drm_ttm_backend *backend)
|
|||
|
||||
|
||||
static int drm_agp_populate(struct drm_ttm_backend *backend,
|
||||
unsigned long num_pages, struct page **pages)
|
||||
unsigned long num_pages, struct page **pages,
|
||||
struct page *dummy_read_page)
|
||||
{
|
||||
struct drm_agp_ttm_backend *agp_be =
|
||||
container_of(backend, struct drm_agp_ttm_backend, backend);
|
||||
struct page **cur_page, **last_page = pages + num_pages;
|
||||
DRM_AGP_MEM *mem;
|
||||
int dummy_page_count = 0;
|
||||
|
||||
if (drm_alloc_memctl(num_pages * sizeof(void *)))
|
||||
return -1;
|
||||
|
|
@ -528,8 +530,16 @@ static int drm_agp_populate(struct drm_ttm_backend *backend,
|
|||
|
||||
DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count);
|
||||
mem->page_count = 0;
|
||||
for (cur_page = pages; cur_page < last_page; ++cur_page)
|
||||
mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*cur_page));
|
||||
for (cur_page = pages; cur_page < last_page; ++cur_page) {
|
||||
struct page *page = *cur_page;
|
||||
if (!page) {
|
||||
page = dummy_read_page;
|
||||
++dummy_page_count;
|
||||
}
|
||||
mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(page));
|
||||
}
|
||||
if (dummy_page_count)
|
||||
DRM_DEBUG("Mapped %d dummy pages\n", dummy_page_count);
|
||||
agp_be->mem = mem;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ void drm_bo_add_to_lru(struct drm_buffer_object *bo)
|
|||
|
||||
DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
|
||||
|
||||
if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))
|
||||
if (!(bo->mem.proposed_flags & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))
|
||||
|| bo->mem.mem_type != bo->pinned_mem_type) {
|
||||
man = &bo->dev->bm.man[bo->mem.mem_type];
|
||||
list_add_tail(&bo->lru, &man->lru);
|
||||
|
|
@ -137,27 +137,32 @@ static int drm_bo_add_ttm(struct drm_buffer_object *bo)
|
|||
{
|
||||
struct drm_device *dev = bo->dev;
|
||||
int ret = 0;
|
||||
uint32_t page_flags = 0;
|
||||
|
||||
DRM_ASSERT_LOCKED(&bo->mutex);
|
||||
bo->ttm = NULL;
|
||||
|
||||
if (bo->mem.proposed_flags & DRM_BO_FLAG_WRITE)
|
||||
page_flags |= DRM_TTM_PAGE_WRITE;
|
||||
|
||||
switch (bo->type) {
|
||||
case drm_bo_type_dc:
|
||||
case drm_bo_type_device:
|
||||
case drm_bo_type_kernel:
|
||||
bo->ttm = drm_ttm_init(dev, bo->num_pages << PAGE_SHIFT);
|
||||
bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT,
|
||||
page_flags, dev->bm.dummy_read_page);
|
||||
if (!bo->ttm)
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
case drm_bo_type_user:
|
||||
bo->ttm = drm_ttm_init(dev, bo->num_pages << PAGE_SHIFT);
|
||||
bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT,
|
||||
page_flags | DRM_TTM_PAGE_USER,
|
||||
dev->bm.dummy_read_page);
|
||||
if (!bo->ttm)
|
||||
ret = -ENOMEM;
|
||||
|
||||
ret = drm_ttm_set_user(bo->ttm, current,
|
||||
bo->mem.mask & DRM_BO_FLAG_WRITE,
|
||||
bo->buffer_start,
|
||||
bo->num_pages,
|
||||
dev->bm.dummy_read_page);
|
||||
bo->num_pages);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -199,7 +204,7 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
|
|||
goto out_err;
|
||||
|
||||
if (mem->mem_type != DRM_BO_MEM_LOCAL) {
|
||||
ret = drm_bind_ttm(bo->ttm, mem);
|
||||
ret = drm_ttm_bind(bo->ttm, mem);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
|
|
@ -209,11 +214,11 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
|
|||
|
||||
struct drm_bo_mem_reg *old_mem = &bo->mem;
|
||||
uint64_t save_flags = old_mem->flags;
|
||||
uint64_t save_mask = old_mem->mask;
|
||||
uint64_t save_proposed_flags = old_mem->proposed_flags;
|
||||
|
||||
*old_mem = *mem;
|
||||
mem->mm_node = NULL;
|
||||
old_mem->mask = save_mask;
|
||||
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) &&
|
||||
|
|
@ -262,7 +267,7 @@ out_err:
|
|||
new_man = &bm->man[bo->mem.mem_type];
|
||||
if ((new_man->flags & _DRM_FLAG_MEMTYPE_FIXED) && bo->ttm) {
|
||||
drm_ttm_unbind(bo->ttm);
|
||||
drm_destroy_ttm(bo->ttm);
|
||||
drm_ttm_destroy(bo->ttm);
|
||||
bo->ttm = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +424,7 @@ static void drm_bo_destroy_locked(struct drm_buffer_object *bo)
|
|||
|
||||
if (bo->ttm) {
|
||||
drm_ttm_unbind(bo->ttm);
|
||||
drm_destroy_ttm(bo->ttm);
|
||||
drm_ttm_destroy(bo->ttm);
|
||||
bo->ttm = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -702,7 +707,7 @@ static int drm_bo_evict(struct drm_buffer_object *bo, unsigned mem_type,
|
|||
evict_mem.mm_node = NULL;
|
||||
|
||||
evict_mem = bo->mem;
|
||||
evict_mem.mask = dev->driver->bo_driver->evict_mask(bo);
|
||||
evict_mem.proposed_flags = dev->driver->bo_driver->evict_flags(bo);
|
||||
ret = drm_bo_mem_space(bo, &evict_mem, no_wait);
|
||||
|
||||
if (ret) {
|
||||
|
|
@ -866,7 +871,7 @@ int drm_bo_mem_space(struct drm_buffer_object *bo,
|
|||
|
||||
type_ok = drm_bo_mt_compatible(man,
|
||||
bo->type == drm_bo_type_user,
|
||||
mem_type, mem->mask,
|
||||
mem_type, mem->proposed_flags,
|
||||
&cur_flags);
|
||||
|
||||
if (!type_ok)
|
||||
|
|
@ -918,7 +923,7 @@ int drm_bo_mem_space(struct drm_buffer_object *bo,
|
|||
if (!drm_bo_mt_compatible(man,
|
||||
bo->type == drm_bo_type_user,
|
||||
mem_type,
|
||||
mem->mask,
|
||||
mem->proposed_flags,
|
||||
&cur_flags))
|
||||
continue;
|
||||
|
||||
|
|
@ -938,11 +943,25 @@ int drm_bo_mem_space(struct drm_buffer_object *bo,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_bo_mem_space);
|
||||
|
||||
static int drm_bo_new_mask(struct drm_buffer_object *bo,
|
||||
uint64_t new_flags, uint64_t used_mask)
|
||||
/*
|
||||
* drm_bo_propose_flags:
|
||||
*
|
||||
* @bo: the buffer object getting new flags
|
||||
*
|
||||
* @new_flags: the new set of proposed flag bits
|
||||
*
|
||||
* @new_mask: the mask of bits changed in new_flags
|
||||
*
|
||||
* Modify the proposed_flag bits in @bo
|
||||
*/
|
||||
static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,
|
||||
uint64_t new_flags, uint64_t new_mask)
|
||||
{
|
||||
uint32_t new_props;
|
||||
uint32_t new_access;
|
||||
|
||||
/* Copy unchanging bits from existing proposed_flags */
|
||||
DRM_FLAG_MASKED(new_flags, bo->mem.proposed_flags, ~new_mask);
|
||||
|
||||
if (bo->type == drm_bo_type_user &&
|
||||
((new_flags & (DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING)) !=
|
||||
(DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING))) {
|
||||
|
|
@ -950,7 +969,7 @@ static int drm_bo_new_mask(struct drm_buffer_object *bo,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((used_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
|
||||
if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
|
||||
DRM_ERROR("DRM_BO_FLAG_NO_EVICT is only available to priviliged processes.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
|
@ -960,15 +979,15 @@ static int drm_bo_new_mask(struct drm_buffer_object *bo,
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
new_props = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE |
|
||||
DRM_BO_FLAG_READ);
|
||||
new_access = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE |
|
||||
DRM_BO_FLAG_READ);
|
||||
|
||||
if (!new_props) {
|
||||
if (new_access == 0) {
|
||||
DRM_ERROR("Invalid buffer object rwx properties\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bo->mem.mask = new_flags;
|
||||
bo->mem.proposed_flags = new_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1103,8 +1122,8 @@ static int drm_bo_wait_unfenced(struct drm_buffer_object *bo, int no_wait,
|
|||
|
||||
ret = 0;
|
||||
mutex_unlock(&bo->mutex);
|
||||
DRM_WAIT_ON(ret, bo->event_queue, 3 * DRM_HZ,
|
||||
!drm_bo_check_unfenced(bo));
|
||||
DRM_WAIT_ON (ret, bo->event_queue, 3 * DRM_HZ,
|
||||
!drm_bo_check_unfenced(bo));
|
||||
mutex_lock(&bo->mutex);
|
||||
if (ret == -EINTR)
|
||||
return -EAGAIN;
|
||||
|
|
@ -1135,12 +1154,17 @@ static void drm_bo_fill_rep_arg(struct drm_buffer_object *bo,
|
|||
rep->size = bo->num_pages * PAGE_SIZE;
|
||||
rep->offset = bo->offset;
|
||||
|
||||
if (bo->type == drm_bo_type_dc)
|
||||
/*
|
||||
* drm_bo_type_device buffers have user-visible
|
||||
* handles which can be used to share across
|
||||
* processes. Hand that back to the application
|
||||
*/
|
||||
if (bo->type == drm_bo_type_device)
|
||||
rep->arg_handle = bo->map_list.user_token;
|
||||
else
|
||||
rep->arg_handle = 0;
|
||||
|
||||
rep->mask = bo->mem.mask;
|
||||
rep->proposed_flags = bo->mem.proposed_flags;
|
||||
rep->buffer_start = bo->buffer_start;
|
||||
rep->fence_flags = bo->fence_type;
|
||||
rep->rep_flags = 0;
|
||||
|
|
@ -1286,7 +1310,7 @@ static void drm_buffer_user_object_unmap(struct drm_file *file_priv,
|
|||
|
||||
/*
|
||||
* bo->mutex locked.
|
||||
* Note that new_mem_flags are NOT transferred to the bo->mem.mask.
|
||||
* Note that new_mem_flags are NOT transferred to the bo->mem.proposed_flags.
|
||||
*/
|
||||
|
||||
int drm_bo_move_buffer(struct drm_buffer_object *bo, uint64_t new_mem_flags,
|
||||
|
|
@ -1312,7 +1336,7 @@ int drm_bo_move_buffer(struct drm_buffer_object *bo, uint64_t new_mem_flags,
|
|||
|
||||
mem.num_pages = bo->num_pages;
|
||||
mem.size = mem.num_pages << PAGE_SHIFT;
|
||||
mem.mask = new_mem_flags;
|
||||
mem.proposed_flags = new_mem_flags;
|
||||
mem.page_alignment = bo->mem.page_alignment;
|
||||
|
||||
mutex_lock(&bm->evict_mutex);
|
||||
|
|
@ -1355,24 +1379,41 @@ out_unlock:
|
|||
|
||||
static int drm_bo_mem_compat(struct drm_bo_mem_reg *mem)
|
||||
{
|
||||
uint32_t flag_diff = (mem->mask ^ mem->flags);
|
||||
uint32_t flag_diff = (mem->proposed_flags ^ mem->flags);
|
||||
|
||||
if ((mem->mask & mem->flags & DRM_BO_MASK_MEM) == 0)
|
||||
if ((mem->proposed_flags & mem->flags & DRM_BO_MASK_MEM) == 0)
|
||||
return 0;
|
||||
if ((flag_diff & DRM_BO_FLAG_CACHED) &&
|
||||
(/* !(mem->mask & DRM_BO_FLAG_CACHED) ||*/
|
||||
(mem->mask & DRM_BO_FLAG_FORCE_CACHING)))
|
||||
(/* !(mem->proposed_flags & DRM_BO_FLAG_CACHED) ||*/
|
||||
(mem->proposed_flags & DRM_BO_FLAG_FORCE_CACHING)))
|
||||
return 0;
|
||||
|
||||
if ((flag_diff & DRM_BO_FLAG_MAPPABLE) &&
|
||||
((mem->mask & DRM_BO_FLAG_MAPPABLE) ||
|
||||
(mem->mask & DRM_BO_FLAG_FORCE_MAPPABLE)))
|
||||
((mem->proposed_flags & DRM_BO_FLAG_MAPPABLE) ||
|
||||
(mem->proposed_flags & DRM_BO_FLAG_FORCE_MAPPABLE)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* bo locked.
|
||||
/**
|
||||
* drm_buffer_object_validate:
|
||||
*
|
||||
* @bo: the buffer object to modify
|
||||
*
|
||||
* @fence_class: the new fence class covering this buffer
|
||||
*
|
||||
* @move_unfenced: a boolean indicating whether switching the
|
||||
* memory space of this buffer should cause the buffer to
|
||||
* be placed on the unfenced list.
|
||||
*
|
||||
* @no_wait: whether this function should return -EBUSY instead
|
||||
* of waiting.
|
||||
*
|
||||
* Change buffer access parameters. This can involve moving
|
||||
* the buffer to the correct memory type, pinning the buffer
|
||||
* or changing the class/type of fence covering this buffer
|
||||
*
|
||||
* Must be called with bo locked.
|
||||
*/
|
||||
|
||||
static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
||||
|
|
@ -1385,8 +1426,8 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
|||
uint32_t ftype;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("New flags 0x%016llx, Old flags 0x%016llx\n",
|
||||
(unsigned long long) bo->mem.mask,
|
||||
DRM_DEBUG("Proposed flags 0x%016llx, Old flags 0x%016llx\n",
|
||||
(unsigned long long) bo->mem.proposed_flags,
|
||||
(unsigned long long) bo->mem.flags);
|
||||
|
||||
ret = driver->fence_type(bo, &fence_class, &ftype);
|
||||
|
|
@ -1427,7 +1468,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
|||
*/
|
||||
|
||||
if (!drm_bo_mem_compat(&bo->mem)) {
|
||||
ret = drm_bo_move_buffer(bo, bo->mem.mask, no_wait,
|
||||
ret = drm_bo_move_buffer(bo, bo->mem.proposed_flags, no_wait,
|
||||
move_unfenced);
|
||||
if (ret) {
|
||||
if (ret != -EAGAIN)
|
||||
|
|
@ -1440,7 +1481,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
|||
* Pinned buffers.
|
||||
*/
|
||||
|
||||
if (bo->mem.mask & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) {
|
||||
if (bo->mem.proposed_flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) {
|
||||
bo->pinned_mem_type = bo->mem.mem_type;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_del_init(&bo->pinned_lru);
|
||||
|
|
@ -1476,7 +1517,13 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
|||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
DRM_FLAG_MASKED(bo->mem.flags, bo->mem.mask, ~DRM_BO_MASK_MEMTYPE);
|
||||
/*
|
||||
* Validation has succeeded, move the access and other
|
||||
* non-mapping-related flag bits from the proposed flags to
|
||||
* the active flags
|
||||
*/
|
||||
|
||||
DRM_FLAG_MASKED(bo->mem.flags, bo->mem.proposed_flags, ~DRM_BO_MASK_MEMTYPE);
|
||||
|
||||
/*
|
||||
* Finally, adjust lru to be sure.
|
||||
|
|
@ -1501,13 +1548,38 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_bo_do_validate:
|
||||
*
|
||||
* @bo: the buffer object
|
||||
*
|
||||
* @flags: access rights, mapping parameters and cacheability. See
|
||||
* the DRM_BO_FLAG_* values in drm.h
|
||||
*
|
||||
* @mask: Which flag values to change; this allows callers to modify
|
||||
* things without knowing the current state of other flags.
|
||||
*
|
||||
* @hint: changes the proceedure for this operation, see the DRM_BO_HINT_*
|
||||
* values in drm.h.
|
||||
*
|
||||
* @fence_class: a driver-specific way of doing fences. Presumably,
|
||||
* this would be used if the driver had more than one submission and
|
||||
* fencing mechanism. At this point, there isn't any use of this
|
||||
* from the user mode code.
|
||||
*
|
||||
* @rep: To be stuffed with the reply from validation
|
||||
*
|
||||
* 'validate' a buffer object. This changes where the buffer is
|
||||
* located, along with changing access modes.
|
||||
*/
|
||||
|
||||
int drm_bo_do_validate(struct drm_buffer_object *bo,
|
||||
uint64_t flags, uint64_t mask, uint32_t hint,
|
||||
uint32_t fence_class,
|
||||
int no_wait,
|
||||
struct drm_bo_info_rep *rep)
|
||||
{
|
||||
int ret;
|
||||
int no_wait = (hint & DRM_BO_HINT_DONT_BLOCK) != 0;
|
||||
|
||||
mutex_lock(&bo->mutex);
|
||||
ret = drm_bo_wait_unfenced(bo, no_wait, 0);
|
||||
|
|
@ -1515,9 +1587,7 @@ int drm_bo_do_validate(struct drm_buffer_object *bo,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
DRM_FLAG_MASKED(flags, bo->mem.mask, ~mask);
|
||||
ret = drm_bo_new_mask(bo, flags, mask);
|
||||
ret = drm_bo_modify_proposed_flags (bo, flags, mask);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
|
@ -1534,11 +1604,42 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL(drm_bo_do_validate);
|
||||
|
||||
/**
|
||||
* drm_bo_handle_validate
|
||||
*
|
||||
* @file_priv: the drm file private, used to get a handle to the user context
|
||||
*
|
||||
* @handle: the buffer object handle
|
||||
*
|
||||
* @flags: access rights, mapping parameters and cacheability. See
|
||||
* the DRM_BO_FLAG_* values in drm.h
|
||||
*
|
||||
* @mask: Which flag values to change; this allows callers to modify
|
||||
* things without knowing the current state of other flags.
|
||||
*
|
||||
* @hint: changes the proceedure for this operation, see the DRM_BO_HINT_*
|
||||
* values in drm.h.
|
||||
*
|
||||
* @fence_class: a driver-specific way of doing fences. Presumably,
|
||||
* this would be used if the driver had more than one submission and
|
||||
* fencing mechanism. At this point, there isn't any use of this
|
||||
* from the user mode code.
|
||||
*
|
||||
* @use_old_fence_class: don't change fence class, pull it from the buffer object
|
||||
*
|
||||
* @rep: To be stuffed with the reply from validation
|
||||
*
|
||||
* @bp_rep: To be stuffed with the buffer object pointer
|
||||
*
|
||||
* Perform drm_bo_do_validate on a buffer referenced by a user-space handle.
|
||||
* Some permissions checking is done on the parameters, otherwise this
|
||||
* is a thin wrapper.
|
||||
*/
|
||||
|
||||
int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
||||
uint32_t fence_class,
|
||||
uint64_t flags, uint64_t mask,
|
||||
uint32_t hint,
|
||||
uint32_t fence_class,
|
||||
int use_old_fence_class,
|
||||
struct drm_bo_info_rep *rep,
|
||||
struct drm_buffer_object **bo_rep)
|
||||
|
|
@ -1546,7 +1647,6 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
|||
struct drm_device *dev = file_priv->minor->dev;
|
||||
struct drm_buffer_object *bo;
|
||||
int ret;
|
||||
int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
bo = drm_lookup_buffer_object(file_priv, handle, 1);
|
||||
|
|
@ -1566,8 +1666,7 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
|||
mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE);
|
||||
|
||||
|
||||
ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class,
|
||||
no_wait, rep);
|
||||
ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, rep);
|
||||
|
||||
if (!ret && bo_rep)
|
||||
*bo_rep = bo;
|
||||
|
|
@ -1635,7 +1734,7 @@ out:
|
|||
int drm_buffer_object_create(struct drm_device *dev,
|
||||
unsigned long size,
|
||||
enum drm_bo_type type,
|
||||
uint64_t mask,
|
||||
uint64_t flags,
|
||||
uint32_t hint,
|
||||
uint32_t page_alignment,
|
||||
unsigned long buffer_start,
|
||||
|
|
@ -1649,7 +1748,7 @@ int drm_buffer_object_create(struct drm_device *dev,
|
|||
size += buffer_start & ~PAGE_MASK;
|
||||
num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
if (num_pages == 0) {
|
||||
DRM_ERROR("Illegal buffer object size %d.\n", size);
|
||||
DRM_ERROR("Illegal buffer object size %ld.\n", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1680,16 +1779,23 @@ int drm_buffer_object_create(struct drm_device *dev,
|
|||
bo->mem.page_alignment = page_alignment;
|
||||
bo->buffer_start = buffer_start & PAGE_MASK;
|
||||
bo->priv_flags = 0;
|
||||
bo->mem.flags = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED |
|
||||
DRM_BO_FLAG_MAPPABLE;
|
||||
bo->mem.mask = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED |
|
||||
DRM_BO_FLAG_MAPPABLE;
|
||||
bo->mem.flags = (DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED |
|
||||
DRM_BO_FLAG_MAPPABLE);
|
||||
bo->mem.proposed_flags = 0;
|
||||
atomic_inc(&bm->count);
|
||||
ret = drm_bo_new_mask(bo, mask, mask);
|
||||
/*
|
||||
* Use drm_bo_modify_proposed_flags to error-check the proposed flags
|
||||
*/
|
||||
ret = drm_bo_modify_proposed_flags (bo, flags, flags);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
if (bo->type == drm_bo_type_dc) {
|
||||
/*
|
||||
* For drm_bo_type_device buffers, allocate
|
||||
* address space from the device so that applications
|
||||
* can mmap the buffer from there
|
||||
*/
|
||||
if (bo->type == drm_bo_type_device) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = drm_bo_setup_vm_locked(bo);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
|
@ -1752,20 +1858,28 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_dc;
|
||||
/*
|
||||
* If the buffer creation request comes in with a starting address,
|
||||
* that points at the desired user pages to map. Otherwise, create
|
||||
* a drm_bo_type_device buffer, which uses pages allocated from the kernel
|
||||
*/
|
||||
bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_device;
|
||||
|
||||
/*
|
||||
* User buffers cannot be shared
|
||||
*/
|
||||
if (bo_type == drm_bo_type_user)
|
||||
req->mask &= ~DRM_BO_FLAG_SHAREABLE;
|
||||
req->flags &= ~DRM_BO_FLAG_SHAREABLE;
|
||||
|
||||
ret = drm_buffer_object_create(file_priv->minor->dev,
|
||||
req->size, bo_type, req->mask,
|
||||
req->size, bo_type, req->flags,
|
||||
req->hint, req->page_alignment,
|
||||
req->buffer_start, &entry);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = drm_bo_add_user_object(file_priv, entry,
|
||||
req->mask & DRM_BO_FLAG_SHAREABLE);
|
||||
req->flags & DRM_BO_FLAG_SHAREABLE);
|
||||
if (ret) {
|
||||
drm_bo_usage_deref_unlocked(&entry);
|
||||
goto out;
|
||||
|
|
@ -1796,11 +1910,17 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class,
|
||||
/*
|
||||
* validate the buffer. note that 'fence_class' will be unused
|
||||
* as we pass use_old_fence_class=1 here. Note also that
|
||||
* the libdrm API doesn't pass fence_class to the kernel,
|
||||
* so it's a good thing it isn't used here.
|
||||
*/
|
||||
ret = drm_bo_handle_validate(file_priv, req->handle,
|
||||
req->flags,
|
||||
req->mask,
|
||||
req->hint | DRM_BO_HINT_DONT_FENCE,
|
||||
1,
|
||||
req->fence_class, 1,
|
||||
rep, NULL);
|
||||
|
||||
(void) drm_bo_read_unlock(&dev->bm.bm_lock);
|
||||
|
|
@ -1951,7 +2071,7 @@ static int drm_bo_leave_list(struct drm_buffer_object *bo,
|
|||
DRM_ERROR("A DRM_BO_NO_EVICT buffer present at "
|
||||
"cleanup. Removing flag and evicting.\n");
|
||||
bo->mem.flags &= ~DRM_BO_FLAG_NO_EVICT;
|
||||
bo->mem.mask &= ~DRM_BO_FLAG_NO_EVICT;
|
||||
bo->mem.proposed_flags &= ~DRM_BO_FLAG_NO_EVICT;
|
||||
}
|
||||
|
||||
if (bo->mem.mem_type == mem_type)
|
||||
|
|
@ -2502,6 +2622,14 @@ void drm_bo_unmap_virtual(struct drm_buffer_object *bo)
|
|||
unmap_mapping_range(dev->dev_mapping, offset, holelen, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_bo_takedown_vm_locked:
|
||||
*
|
||||
* @bo: the buffer object to remove any drm device mapping
|
||||
*
|
||||
* Remove any associated vm mapping on the drm device node that
|
||||
* would have been created for a drm_bo_type_device buffer
|
||||
*/
|
||||
static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
|
||||
{
|
||||
struct drm_map_list *list;
|
||||
|
|
@ -2509,7 +2637,7 @@ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
|
|||
struct drm_device *dev = bo->dev;
|
||||
|
||||
DRM_ASSERT_LOCKED(&dev->struct_mutex);
|
||||
if (bo->type != drm_bo_type_dc)
|
||||
if (bo->type != drm_bo_type_device)
|
||||
return;
|
||||
|
||||
list = &bo->map_list;
|
||||
|
|
@ -2532,6 +2660,16 @@ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
|
|||
drm_bo_usage_deref_locked(&bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_bo_setup_vm_locked:
|
||||
*
|
||||
* @bo: the buffer to allocate address space for
|
||||
*
|
||||
* Allocate address space in the drm device so that applications
|
||||
* can mmap the buffer and access the contents. This only
|
||||
* applies to drm_bo_type_device objects as others are not
|
||||
* placed in the drm device address space.
|
||||
*/
|
||||
static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
|
||||
{
|
||||
struct drm_map_list *list = &bo->map_list;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo,
|
|||
struct drm_ttm *ttm = bo->ttm;
|
||||
struct drm_bo_mem_reg *old_mem = &bo->mem;
|
||||
uint64_t save_flags = old_mem->flags;
|
||||
uint64_t save_mask = old_mem->mask;
|
||||
uint64_t save_proposed_flags = old_mem->proposed_flags;
|
||||
int ret;
|
||||
|
||||
if (old_mem->mem_type == DRM_BO_MEM_TT) {
|
||||
|
|
@ -71,14 +71,14 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo,
|
|||
save_flags = old_mem->flags;
|
||||
}
|
||||
if (new_mem->mem_type != DRM_BO_MEM_LOCAL) {
|
||||
ret = drm_bind_ttm(ttm, new_mem);
|
||||
ret = drm_ttm_bind(ttm, new_mem);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*old_mem = *new_mem;
|
||||
new_mem->mm_node = NULL;
|
||||
old_mem->mask = save_mask;
|
||||
old_mem->proposed_flags = save_proposed_flags;
|
||||
DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ int drm_bo_move_memcpy(struct drm_buffer_object *bo,
|
|||
void *new_iomap;
|
||||
int ret;
|
||||
uint64_t save_flags = old_mem->flags;
|
||||
uint64_t save_mask = old_mem->mask;
|
||||
uint64_t save_proposed_flags = old_mem->proposed_flags;
|
||||
unsigned long i;
|
||||
unsigned long page;
|
||||
unsigned long add = 0;
|
||||
|
|
@ -256,12 +256,12 @@ out2:
|
|||
|
||||
*old_mem = *new_mem;
|
||||
new_mem->mm_node = NULL;
|
||||
old_mem->mask = save_mask;
|
||||
old_mem->proposed_flags = save_proposed_flags;
|
||||
DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
|
||||
|
||||
if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (ttm != NULL)) {
|
||||
drm_ttm_unbind(ttm);
|
||||
drm_destroy_ttm(ttm);
|
||||
drm_ttm_destroy(ttm);
|
||||
bo->ttm = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo,
|
|||
struct drm_bo_mem_reg *old_mem = &bo->mem;
|
||||
int ret;
|
||||
uint64_t save_flags = old_mem->flags;
|
||||
uint64_t save_mask = old_mem->mask;
|
||||
uint64_t save_proposed_flags = old_mem->proposed_flags;
|
||||
struct drm_buffer_object *old_obj;
|
||||
|
||||
if (bo->fence)
|
||||
|
|
@ -366,7 +366,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo,
|
|||
|
||||
if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (bo->ttm != NULL)) {
|
||||
drm_ttm_unbind(bo->ttm);
|
||||
drm_destroy_ttm(bo->ttm);
|
||||
drm_ttm_destroy(bo->ttm);
|
||||
bo->ttm = NULL;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -400,7 +400,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo,
|
|||
|
||||
*old_mem = *new_mem;
|
||||
new_mem->mm_node = NULL;
|
||||
old_mem->mask = save_mask;
|
||||
old_mem->proposed_flags = save_proposed_flags;
|
||||
DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
|
|||
|
||||
if (!(bo->mem.flags & DRM_BO_FLAG_MAPPABLE)) {
|
||||
unsigned long _end = jiffies + 3*DRM_HZ;
|
||||
uint32_t new_mask = bo->mem.mask |
|
||||
uint32_t new_mask = bo->mem.proposed_flags |
|
||||
DRM_BO_FLAG_MAPPABLE |
|
||||
DRM_BO_FLAG_FORCE_MAPPABLE;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETOUTPUT, drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
|
|
@ -131,6 +135,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_MM_INIT, drm_mm_init_ioctl,
|
||||
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl,
|
||||
|
|
|
|||
|
|
@ -71,18 +71,100 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vblank_disable_fn(unsigned long arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->num_crtcs; i++)
|
||||
if (atomic_read(&dev->vblank_refcount[i]) == 0)
|
||||
dev->driver->disable_vblank(dev, i);
|
||||
}
|
||||
|
||||
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||
{
|
||||
int i, ret = -ENOMEM;
|
||||
|
||||
setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
|
||||
(unsigned long)dev);
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
atomic_set(&dev->vbl_signal_pending, 0);
|
||||
dev->num_crtcs = num_crtcs;
|
||||
|
||||
dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vbl_queue)
|
||||
goto err;
|
||||
|
||||
dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vbl_sigs)
|
||||
goto err;
|
||||
|
||||
dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->_vblank_count)
|
||||
goto err;
|
||||
|
||||
dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_refcount)
|
||||
goto err;
|
||||
|
||||
dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
|
||||
if (!dev->last_vblank)
|
||||
goto err;
|
||||
|
||||
dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_premodeset)
|
||||
goto err;
|
||||
|
||||
dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_offset)
|
||||
goto err;
|
||||
|
||||
/* Zero per-crtc vblank stuff */
|
||||
for (i = 0; i < num_crtcs; i++) {
|
||||
init_waitqueue_head(&dev->vbl_queue[i]);
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs[i]);
|
||||
atomic_set(&dev->_vblank_count[i], 0);
|
||||
atomic_set(&dev->vblank_refcount[i], 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
|
||||
num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
|
||||
num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_init);
|
||||
|
||||
/**
|
||||
* Install IRQ handler.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
*
|
||||
* Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
|
||||
* Initializes the IRQ related data. Installs the handler, calling the driver
|
||||
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
|
||||
* before and after the installation.
|
||||
*/
|
||||
int drm_irq_install(struct drm_device * dev)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
unsigned long sh_flags = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
|
|
@ -106,18 +188,7 @@ int drm_irq_install(struct drm_device * dev)
|
|||
dev->irq_enabled = 1;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
|
||||
init_waitqueue_head(&dev->vbl_queue);
|
||||
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs);
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs2);
|
||||
|
||||
dev->vbl_pending = 0;
|
||||
}
|
||||
DRM_DEBUG("irq=%d\n", dev->irq);
|
||||
|
||||
/* Before installing handler */
|
||||
dev->driver->irq_preinstall(dev);
|
||||
|
|
@ -136,9 +207,14 @@ int drm_irq_install(struct drm_device * dev)
|
|||
}
|
||||
|
||||
/* After installing handler */
|
||||
dev->driver->irq_postinstall(dev);
|
||||
ret = dev->driver->irq_postinstall(dev);
|
||||
if (ret < 0) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
dev->irq_enabled = 0;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_irq_install);
|
||||
|
||||
|
|
@ -164,7 +240,7 @@ int drm_irq_uninstall(struct drm_device * dev)
|
|||
if (!irq_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
|
||||
DRM_DEBUG("irq=%d\n", dev->irq);
|
||||
|
||||
dev->driver->irq_uninstall(dev);
|
||||
|
||||
|
|
@ -212,6 +288,143 @@ int drm_control(struct drm_device *dev, void *data,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_vblank_count - retrieve "cooked" vblank counter value
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to retrieve
|
||||
*
|
||||
* Fetches the "cooked" vblank count value that represents the number of
|
||||
* vblank events since the system was booted, including lost events due to
|
||||
* modesetting activity.
|
||||
*/
|
||||
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
return atomic_read(&dev->_vblank_count[crtc]) +
|
||||
dev->vblank_offset[crtc];
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_count);
|
||||
|
||||
/**
|
||||
* drm_update_vblank_count - update the master vblank counter
|
||||
* @dev: DRM device
|
||||
* @crtc: counter to update
|
||||
*
|
||||
* Call back into the driver to update the appropriate vblank counter
|
||||
* (specified by @crtc). Deal with wraparound, if it occurred, and
|
||||
* update the last read value so we can deal with wraparound on the next
|
||||
* call if necessary.
|
||||
*/
|
||||
void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
u32 cur_vblank, diff;
|
||||
|
||||
/*
|
||||
* Interrupts were disabled prior to this call, so deal with counter
|
||||
* wrap if needed.
|
||||
* NOTE! It's possible we lost a full dev->max_vblank_count events
|
||||
* here if the register is small or we had vblank interrupts off for
|
||||
* a long time.
|
||||
*/
|
||||
cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
if (cur_vblank < dev->last_vblank[crtc]) {
|
||||
diff = dev->max_vblank_count -
|
||||
dev->last_vblank[crtc];
|
||||
diff += cur_vblank;
|
||||
} else {
|
||||
diff = cur_vblank - dev->last_vblank[crtc];
|
||||
}
|
||||
dev->last_vblank[crtc] = cur_vblank;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
atomic_add(diff, &dev->_vblank_count[crtc]);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_update_vblank_count);
|
||||
|
||||
/**
|
||||
* drm_vblank_get - get a reference count on vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which CRTC to own
|
||||
*
|
||||
* Acquire a reference count on vblank events to avoid having them disabled
|
||||
* while in use. Note callers will probably want to update the master counter
|
||||
* using drm_update_vblank_count() above before calling this routine so that
|
||||
* wakeups occur on the right vblank event.
|
||||
*
|
||||
* RETURNS
|
||||
* Zero on success, nonzero on failure.
|
||||
*/
|
||||
int drm_vblank_get(struct drm_device *dev, int crtc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Going from 0->1 means we have to enable interrupts again */
|
||||
if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
|
||||
ret = dev->driver->enable_vblank(dev, crtc);
|
||||
if (ret)
|
||||
atomic_dec(&dev->vblank_refcount[crtc]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_get);
|
||||
|
||||
/**
|
||||
* drm_vblank_put - give up ownership of vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to give up
|
||||
*
|
||||
* Release ownership of a given vblank counter, turning off interrupts
|
||||
* if possible.
|
||||
*/
|
||||
void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||
{
|
||||
/* Last user schedules interrupt disable */
|
||||
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
||||
mod_timer(&dev->vblank_disable_timer,
|
||||
round_jiffies_relative(DRM_HZ));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_put);
|
||||
|
||||
/**
|
||||
* drm_modeset_ctl - handle vblank event counter changes across mode switch
|
||||
* @DRM_IOCTL_ARGS: standard ioctl arguments
|
||||
*
|
||||
* Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
|
||||
* ioctls around modesetting so that any lost vblank events are accounted for.
|
||||
*/
|
||||
int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_modeset_ctl *modeset = data;
|
||||
int crtc, ret = 0;
|
||||
u32 new;
|
||||
|
||||
crtc = modeset->arg;
|
||||
if (crtc >= dev->num_crtcs) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (modeset->cmd) {
|
||||
case _DRM_PRE_MODESET:
|
||||
dev->vblank_premodeset[crtc] =
|
||||
dev->driver->get_vblank_counter(dev, crtc);
|
||||
break;
|
||||
case _DRM_POST_MODESET:
|
||||
new = dev->driver->get_vblank_counter(dev, crtc);
|
||||
dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for VBLANK.
|
||||
*
|
||||
|
|
@ -231,12 +444,13 @@ int drm_control(struct drm_device *dev, void *data,
|
|||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
union drm_wait_vblank *vblwait = data;
|
||||
struct timeval now;
|
||||
int ret = 0;
|
||||
unsigned int flags, seq;
|
||||
unsigned int flags, seq, crtc;
|
||||
|
||||
if ((!dev->irq) || (!dev->irq_enabled))
|
||||
return -EINVAL;
|
||||
|
|
@ -250,13 +464,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
}
|
||||
|
||||
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
|
||||
DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
|
||||
if (crtc >= dev->num_crtcs)
|
||||
return -EINVAL;
|
||||
|
||||
seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
|
||||
: &dev->vbl_received);
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
seq = drm_vblank_count(dev, crtc);
|
||||
|
||||
switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
|
||||
case _DRM_VBLANK_RELATIVE:
|
||||
|
|
@ -275,8 +489,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
|
||||
if (flags & _DRM_VBLANK_SIGNAL) {
|
||||
unsigned long irqflags;
|
||||
struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
|
||||
? &dev->vbl_sigs2 : &dev->vbl_sigs;
|
||||
struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
|
||||
struct drm_vbl_sig *vbl_sig;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
|
|
@ -297,22 +510,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
}
|
||||
}
|
||||
|
||||
if (dev->vbl_pending >= 100) {
|
||||
if (atomic_read(&dev->vbl_signal_pending) >= 100) {
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev->vbl_pending++;
|
||||
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
if (!
|
||||
(vbl_sig =
|
||||
drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
|
||||
vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!vbl_sig)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (ret) {
|
||||
drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
|
||||
atomic_inc(&dev->vbl_signal_pending);
|
||||
|
||||
vbl_sig->sequence = vblwait->request.sequence;
|
||||
vbl_sig->info.si_signo = vblwait->request.signal;
|
||||
|
|
@ -326,17 +543,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
|
||||
vblwait->reply.sequence = seq;
|
||||
} else {
|
||||
if (flags & _DRM_VBLANK_SECONDARY) {
|
||||
if (dev->driver->vblank_wait2)
|
||||
ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
|
||||
} else if (dev->driver->vblank_wait)
|
||||
ret =
|
||||
dev->driver->vblank_wait(dev,
|
||||
&vblwait->request.sequence);
|
||||
unsigned long cur_vblank;
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
|
||||
(((cur_vblank = drm_vblank_count(dev, crtc))
|
||||
- vblwait->request.sequence) <= (1 << 23)));
|
||||
drm_vblank_put(dev, crtc);
|
||||
do_gettimeofday(&now);
|
||||
|
||||
vblwait->reply.tval_sec = now.tv_sec;
|
||||
vblwait->reply.tval_usec = now.tv_usec;
|
||||
vblwait->reply.sequence = cur_vblank;
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -347,43 +567,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
* Send the VBLANK signals.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param crtc CRTC where the vblank event occurred
|
||||
*
|
||||
* Sends a signal for each task in drm_device::vbl_sigs and empties the list.
|
||||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
void drm_vbl_send_signals(struct drm_device * dev)
|
||||
static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
|
||||
{
|
||||
struct drm_vbl_sig *vbl_sig, *tmp;
|
||||
struct list_head *vbl_sigs;
|
||||
unsigned int vbl_seq;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, flags);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct drm_vbl_sig *vbl_sig, *tmp;
|
||||
struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
|
||||
unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
|
||||
&dev->vbl_received);
|
||||
vbl_sigs = &dev->vbl_sigs[crtc];
|
||||
vbl_seq = drm_vblank_count(dev, crtc);
|
||||
|
||||
list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
vbl_sig->info.si_code = vbl_seq;
|
||||
send_sig_info(vbl_sig->info.si_signo,
|
||||
&vbl_sig->info, vbl_sig->task);
|
||||
list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
vbl_sig->info.si_code = vbl_seq;
|
||||
send_sig_info(vbl_sig->info.si_signo,
|
||||
&vbl_sig->info, vbl_sig->task);
|
||||
|
||||
list_del(&vbl_sig->head);
|
||||
list_del(&vbl_sig->head);
|
||||
|
||||
drm_free(vbl_sig, sizeof(*vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->vbl_pending--;
|
||||
}
|
||||
}
|
||||
drm_free(vbl_sig, sizeof(*vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
atomic_dec(&dev->vbl_signal_pending);
|
||||
drm_vblank_put(dev, crtc);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vbl_send_signals);
|
||||
|
||||
/**
|
||||
* drm_handle_vblank - handle a vblank event
|
||||
* @dev: DRM device
|
||||
* @crtc: where this event occurred
|
||||
*
|
||||
* Drivers should call this routine in their vblank interrupt handlers to
|
||||
* update the vblank counter and send any signals that may be pending.
|
||||
*/
|
||||
void drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
DRM_WAKEUP(&dev->vbl_queue[crtc]);
|
||||
drm_vbl_send_signals(dev, crtc);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_handle_vblank);
|
||||
|
||||
/**
|
||||
* Tasklet wrapper function.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item,
|
|||
item->owner = priv;
|
||||
|
||||
ret = drm_ht_just_insert_please(&dev->object_hash, &item->hash,
|
||||
(unsigned long)item, 32, 0, 0);
|
||||
(unsigned long)item, 31, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -262,7 +262,8 @@ struct drm_ttm_backend;
|
|||
struct drm_ttm_backend_func {
|
||||
int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend);
|
||||
int (*populate) (struct drm_ttm_backend *backend,
|
||||
unsigned long num_pages, struct page **pages);
|
||||
unsigned long num_pages, struct page **pages,
|
||||
struct page *dummy_read_page);
|
||||
void (*clear) (struct drm_ttm_backend *backend);
|
||||
int (*bind) (struct drm_ttm_backend *backend,
|
||||
struct drm_bo_mem_reg *bo_mem);
|
||||
|
|
@ -296,8 +297,10 @@ struct drm_ttm {
|
|||
|
||||
};
|
||||
|
||||
extern struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size);
|
||||
extern int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem);
|
||||
extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size,
|
||||
uint32_t page_flags,
|
||||
struct page *dummy_read_page);
|
||||
extern int drm_ttm_bind(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem);
|
||||
extern void drm_ttm_unbind(struct drm_ttm *ttm);
|
||||
extern void drm_ttm_evict(struct drm_ttm *ttm);
|
||||
extern void drm_ttm_fixup_caching(struct drm_ttm *ttm);
|
||||
|
|
@ -306,10 +309,8 @@ extern void drm_ttm_cache_flush(void);
|
|||
extern int drm_ttm_populate(struct drm_ttm *ttm);
|
||||
extern int drm_ttm_set_user(struct drm_ttm *ttm,
|
||||
struct task_struct *tsk,
|
||||
int write,
|
||||
unsigned long start,
|
||||
unsigned long num_pages,
|
||||
struct page *dummy_read_page);
|
||||
unsigned long num_pages);
|
||||
|
||||
/*
|
||||
* Destroy a ttm. The user normally calls drmRmMap or a similar IOCTL to do
|
||||
|
|
@ -317,7 +318,7 @@ extern int drm_ttm_set_user(struct drm_ttm *ttm,
|
|||
* Otherwise it is called when the last vma exits.
|
||||
*/
|
||||
|
||||
extern int drm_destroy_ttm(struct drm_ttm *ttm);
|
||||
extern int drm_ttm_destroy(struct drm_ttm *ttm);
|
||||
|
||||
#define DRM_FLAG_MASKED(_old, _new, _mask) {\
|
||||
(_old) ^= (((_old) ^ (_new)) & (_mask)); \
|
||||
|
|
@ -330,14 +331,47 @@ extern int drm_destroy_ttm(struct drm_ttm *ttm);
|
|||
* Page flags.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This ttm should not be cached by the CPU
|
||||
*/
|
||||
#define DRM_TTM_PAGE_UNCACHED (1 << 0)
|
||||
/*
|
||||
* This flat is not used at this time; I don't know what the
|
||||
* intent was
|
||||
*/
|
||||
#define DRM_TTM_PAGE_USED (1 << 1)
|
||||
/*
|
||||
* This flat is not used at this time; I don't know what the
|
||||
* intent was
|
||||
*/
|
||||
#define DRM_TTM_PAGE_BOUND (1 << 2)
|
||||
/*
|
||||
* This flat is not used at this time; I don't know what the
|
||||
* intent was
|
||||
*/
|
||||
#define DRM_TTM_PAGE_PRESENT (1 << 3)
|
||||
/*
|
||||
* The array of page pointers was allocated with vmalloc
|
||||
* instead of drm_calloc.
|
||||
*/
|
||||
#define DRM_TTM_PAGE_VMALLOC (1 << 4)
|
||||
/*
|
||||
* This ttm is mapped from user space
|
||||
*/
|
||||
#define DRM_TTM_PAGE_USER (1 << 5)
|
||||
#define DRM_TTM_PAGE_USER_WRITE (1 << 6)
|
||||
/*
|
||||
* This ttm will be written to by the GPU
|
||||
*/
|
||||
#define DRM_TTM_PAGE_WRITE (1 << 6)
|
||||
/*
|
||||
* This ttm was mapped to the GPU, and so the contents may have
|
||||
* been modified
|
||||
*/
|
||||
#define DRM_TTM_PAGE_USER_DIRTY (1 << 7)
|
||||
/*
|
||||
* This flag is not used at this time; I don't know what the
|
||||
* intent was.
|
||||
*/
|
||||
#define DRM_TTM_PAGE_USER_DMA (1 << 8)
|
||||
|
||||
/***************************************************
|
||||
|
|
@ -350,16 +384,50 @@ struct drm_bo_mem_reg {
|
|||
unsigned long num_pages;
|
||||
uint32_t page_alignment;
|
||||
uint32_t mem_type;
|
||||
/*
|
||||
* Current buffer status flags, indicating
|
||||
* where the buffer is located and which
|
||||
* access modes are in effect
|
||||
*/
|
||||
uint64_t flags;
|
||||
uint64_t mask;
|
||||
/**
|
||||
* These are the flags proposed for
|
||||
* a validate operation. If the
|
||||
* validate succeeds, they'll get moved
|
||||
* into the flags field
|
||||
*/
|
||||
uint64_t proposed_flags;
|
||||
|
||||
uint32_t desired_tile_stride;
|
||||
uint32_t hw_tile_stride;
|
||||
};
|
||||
|
||||
enum drm_bo_type {
|
||||
drm_bo_type_dc,
|
||||
/*
|
||||
* drm_bo_type_device are 'normal' drm allocations,
|
||||
* pages are allocated from within the kernel automatically
|
||||
* and the objects can be mmap'd from the drm device. Each
|
||||
* drm_bo_type_device object has a unique name which can be
|
||||
* used by other processes to share access to the underlying
|
||||
* buffer.
|
||||
*/
|
||||
drm_bo_type_device,
|
||||
/*
|
||||
* drm_bo_type_user are buffers of pages that already exist
|
||||
* in the process address space. They are more limited than
|
||||
* drm_bo_type_device buffers in that they must always
|
||||
* remain cached (as we assume the user pages are mapped cached),
|
||||
* and they are not sharable to other processes through DRM
|
||||
* (although, regular shared memory should still work fine).
|
||||
*/
|
||||
drm_bo_type_user,
|
||||
drm_bo_type_kernel, /* for initial kernel allocations */
|
||||
/*
|
||||
* drm_bo_type_kernel are buffers that exist solely for use
|
||||
* within the kernel. The pages cannot be mapped into the
|
||||
* process. One obvious use would be for the ring
|
||||
* buffer where user access would not (ideally) be required.
|
||||
*/
|
||||
drm_bo_type_kernel,
|
||||
};
|
||||
|
||||
struct drm_buffer_object {
|
||||
|
|
@ -476,9 +544,36 @@ struct drm_bo_driver {
|
|||
int (*invalidate_caches) (struct drm_device *dev, uint64_t flags);
|
||||
int (*init_mem_type) (struct drm_device *dev, uint32_t type,
|
||||
struct drm_mem_type_manager *man);
|
||||
uint32_t(*evict_mask) (struct drm_buffer_object *bo);
|
||||
/*
|
||||
* evict_flags:
|
||||
*
|
||||
* @bo: the buffer object to be evicted
|
||||
*
|
||||
* Return the bo flags for a buffer which is not mapped to the hardware.
|
||||
* These will be placed in proposed_flags so that when the move is
|
||||
* finished, they'll end up in bo->mem.flags
|
||||
*/
|
||||
uint64_t(*evict_flags) (struct drm_buffer_object *bo);
|
||||
/*
|
||||
* move:
|
||||
*
|
||||
* @bo: the buffer to move
|
||||
*
|
||||
* @evict: whether this motion is evicting the buffer from
|
||||
* the graphics address space
|
||||
*
|
||||
* @no_wait: whether this should give up and return -EBUSY
|
||||
* if this move would require sleeping
|
||||
*
|
||||
* @new_mem: the new memory region receiving the buffer
|
||||
*
|
||||
* Move a buffer between two memory regions.
|
||||
*/
|
||||
int (*move) (struct drm_buffer_object *bo,
|
||||
int evict, int no_wait, struct drm_bo_mem_reg *new_mem);
|
||||
/*
|
||||
* ttm_cache_flush
|
||||
*/
|
||||
void (*ttm_cache_flush)(struct drm_ttm *ttm);
|
||||
};
|
||||
|
||||
|
|
@ -519,7 +614,7 @@ extern int drm_fence_buffer_objects(struct drm_device *dev,
|
|||
struct drm_fence_object **used_fence);
|
||||
extern void drm_bo_add_to_lru(struct drm_buffer_object *bo);
|
||||
extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size,
|
||||
enum drm_bo_type type, uint64_t mask,
|
||||
enum drm_bo_type type, uint64_t flags,
|
||||
uint32_t hint, uint32_t page_alignment,
|
||||
unsigned long buffer_start,
|
||||
struct drm_buffer_object **bo);
|
||||
|
|
@ -534,9 +629,8 @@ extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type);
|
|||
extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,
|
||||
unsigned long p_offset, unsigned long p_size);
|
||||
extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
||||
uint32_t fence_class, uint64_t flags,
|
||||
uint64_t mask, uint32_t hint,
|
||||
int use_old_fence_class,
|
||||
uint64_t flags, uint64_t mask, uint32_t hint,
|
||||
uint32_t fence_class, int use_old_fence_class,
|
||||
struct drm_bo_info_rep *rep,
|
||||
struct drm_buffer_object **bo_rep);
|
||||
extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv,
|
||||
|
|
@ -545,7 +639,6 @@ extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_
|
|||
extern int drm_bo_do_validate(struct drm_buffer_object *bo,
|
||||
uint64_t flags, uint64_t mask, uint32_t hint,
|
||||
uint32_t fence_class,
|
||||
int no_wait,
|
||||
struct drm_bo_info_rep *rep);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
|
|||
struct drm_sg_mem *entry;
|
||||
unsigned long pages, i, j;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_SG))
|
||||
return -EINVAL;
|
||||
|
|
@ -82,7 +82,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
|
|||
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages);
|
||||
DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
|
||||
|
||||
entry->pages = pages;
|
||||
entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
|
||||
|
|
@ -123,8 +123,8 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
|
|||
|
||||
entry->handle = ScatterHandle((unsigned long)entry->virtual);
|
||||
|
||||
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
|
||||
DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual);
|
||||
DRM_DEBUG("handle = %08lx\n", entry->handle);
|
||||
DRM_DEBUG("virtual = %p\n", entry->virtual);
|
||||
|
||||
for (i = (unsigned long)entry->virtual, j = 0; j < pages;
|
||||
i += PAGE_SIZE, j++) {
|
||||
|
|
@ -211,7 +211,7 @@ int drm_sg_free(struct drm_device *dev, void *data,
|
|||
if (!entry || entry->handle != request->handle)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("sg free virtual = %p\n", entry->virtual);
|
||||
DRM_DEBUG("virtual = %p\n", entry->virtual);
|
||||
|
||||
drm_sg_cleanup(entry);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ EXPORT_SYMBOL(drm_ttm_cache_flush);
|
|||
* Use kmalloc if possible. Otherwise fall back to vmalloc.
|
||||
*/
|
||||
|
||||
static void ttm_alloc_pages(struct drm_ttm *ttm)
|
||||
static void drm_ttm_alloc_pages(struct drm_ttm *ttm)
|
||||
{
|
||||
unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
|
||||
ttm->pages = NULL;
|
||||
|
|
@ -66,7 +66,7 @@ static void ttm_alloc_pages(struct drm_ttm *ttm)
|
|||
drm_free_memctl(size);
|
||||
}
|
||||
|
||||
static void ttm_free_pages(struct drm_ttm *ttm)
|
||||
static void drm_ttm_free_pages(struct drm_ttm *ttm)
|
||||
{
|
||||
unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ static struct page *drm_ttm_alloc_page(void)
|
|||
* for range of pages in a ttm.
|
||||
*/
|
||||
|
||||
static int drm_set_caching(struct drm_ttm *ttm, int noncached)
|
||||
static int drm_ttm_set_caching(struct drm_ttm *ttm, int noncached)
|
||||
{
|
||||
int i;
|
||||
struct page **cur_page;
|
||||
|
|
@ -145,7 +145,7 @@ static void drm_ttm_free_user_pages(struct drm_ttm *ttm)
|
|||
int i;
|
||||
|
||||
BUG_ON(!(ttm->page_flags & DRM_TTM_PAGE_USER));
|
||||
write = ((ttm->page_flags & DRM_TTM_PAGE_USER_WRITE) != 0);
|
||||
write = ((ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0);
|
||||
dirty = ((ttm->page_flags & DRM_TTM_PAGE_USER_DIRTY) != 0);
|
||||
|
||||
for (i = 0; i < ttm->num_pages; ++i) {
|
||||
|
|
@ -193,7 +193,7 @@ static void drm_ttm_free_alloced_pages(struct drm_ttm *ttm)
|
|||
* Free all resources associated with a ttm.
|
||||
*/
|
||||
|
||||
int drm_destroy_ttm(struct drm_ttm *ttm)
|
||||
int drm_ttm_destroy(struct drm_ttm *ttm)
|
||||
{
|
||||
struct drm_ttm_backend *be;
|
||||
|
||||
|
|
@ -208,14 +208,14 @@ int drm_destroy_ttm(struct drm_ttm *ttm)
|
|||
|
||||
if (ttm->pages) {
|
||||
if (ttm->page_flags & DRM_TTM_PAGE_UNCACHED)
|
||||
drm_set_caching(ttm, 0);
|
||||
drm_ttm_set_caching(ttm, 0);
|
||||
|
||||
if (ttm->page_flags & DRM_TTM_PAGE_USER)
|
||||
drm_ttm_free_user_pages(ttm);
|
||||
else
|
||||
drm_ttm_free_alloced_pages(ttm);
|
||||
|
||||
ttm_free_pages(ttm);
|
||||
drm_ttm_free_pages(ttm);
|
||||
}
|
||||
|
||||
drm_ctl_free(ttm, sizeof(*ttm), DRM_MEM_TTM);
|
||||
|
|
@ -239,23 +239,33 @@ struct page *drm_ttm_get_page(struct drm_ttm *ttm, int index)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_ttm_get_page);
|
||||
|
||||
/**
|
||||
* drm_ttm_set_user:
|
||||
*
|
||||
* @ttm: the ttm to map pages to. This must always be
|
||||
* a freshly created ttm.
|
||||
*
|
||||
* @tsk: a pointer to the address space from which to map
|
||||
* pages.
|
||||
*
|
||||
* @write: a boolean indicating that write access is desired
|
||||
*
|
||||
* start: the starting address
|
||||
*
|
||||
* Map a range of user addresses to a new ttm object. This
|
||||
* provides access to user memory from the graphics device.
|
||||
*/
|
||||
int drm_ttm_set_user(struct drm_ttm *ttm,
|
||||
struct task_struct *tsk,
|
||||
int write,
|
||||
unsigned long start,
|
||||
unsigned long num_pages,
|
||||
struct page *dummy_read_page)
|
||||
unsigned long num_pages)
|
||||
{
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
int ret;
|
||||
int i;
|
||||
int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0;
|
||||
|
||||
BUG_ON(num_pages != ttm->num_pages);
|
||||
|
||||
ttm->dummy_read_page = dummy_read_page;
|
||||
ttm->page_flags |= DRM_TTM_PAGE_USER |
|
||||
((write) ? DRM_TTM_PAGE_USER_WRITE : 0);
|
||||
|
||||
BUG_ON((ttm->page_flags & DRM_TTM_PAGE_USER) == 0);
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
ret = get_user_pages(tsk, mm, start, num_pages,
|
||||
|
|
@ -267,14 +277,17 @@ int drm_ttm_set_user(struct drm_ttm *ttm,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
if (ttm->pages[i] == NULL)
|
||||
ttm->pages[i] = ttm->dummy_read_page;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_ttm_populate:
|
||||
*
|
||||
* @ttm: the object to allocate pages for
|
||||
*
|
||||
* Allocate pages for all unset page entries, then
|
||||
* call the backend to create the hardware mappings
|
||||
*/
|
||||
int drm_ttm_populate(struct drm_ttm *ttm)
|
||||
{
|
||||
struct page *page;
|
||||
|
|
@ -285,21 +298,32 @@ int drm_ttm_populate(struct drm_ttm *ttm)
|
|||
return 0;
|
||||
|
||||
be = ttm->be;
|
||||
for (i = 0; i < ttm->num_pages; ++i) {
|
||||
page = drm_ttm_get_page(ttm, i);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
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);
|
||||
be->func->populate(be, ttm->num_pages, ttm->pages, ttm->dummy_read_page);
|
||||
ttm->state = ttm_unbound;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a ttm.
|
||||
/**
|
||||
* drm_ttm_create:
|
||||
*
|
||||
* @dev: the drm_device
|
||||
*
|
||||
* @size: The size (in bytes) of the desired object
|
||||
*
|
||||
* @page_flags: various DRM_TTM_PAGE_* flags. See drm_object.h.
|
||||
*
|
||||
* Allocate and initialize a ttm, leaving it unpopulated at this time
|
||||
*/
|
||||
|
||||
struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size)
|
||||
struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size,
|
||||
uint32_t page_flags, struct page *dummy_read_page)
|
||||
{
|
||||
struct drm_bo_driver *bo_driver = dev->driver->bo_driver;
|
||||
struct drm_ttm *ttm;
|
||||
|
|
@ -317,21 +341,23 @@ struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size)
|
|||
ttm->destroy = 0;
|
||||
ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
ttm->page_flags = 0;
|
||||
ttm->page_flags = page_flags;
|
||||
|
||||
ttm->dummy_read_page = dummy_read_page;
|
||||
|
||||
/*
|
||||
* Account also for AGP module memory usage.
|
||||
*/
|
||||
|
||||
ttm_alloc_pages(ttm);
|
||||
drm_ttm_alloc_pages(ttm);
|
||||
if (!ttm->pages) {
|
||||
drm_destroy_ttm(ttm);
|
||||
drm_ttm_destroy(ttm);
|
||||
DRM_ERROR("Failed allocating page table\n");
|
||||
return NULL;
|
||||
}
|
||||
ttm->be = bo_driver->create_ttm_backend_entry(dev);
|
||||
if (!ttm->be) {
|
||||
drm_destroy_ttm(ttm);
|
||||
drm_ttm_destroy(ttm);
|
||||
DRM_ERROR("Failed creating ttm backend entry\n");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -339,10 +365,15 @@ struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size)
|
|||
return ttm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unbind a ttm region from the aperture.
|
||||
/**
|
||||
* drm_ttm_evict:
|
||||
*
|
||||
* @ttm: the object to be unbound from the aperture.
|
||||
*
|
||||
* Transition a ttm from bound to evicted, where it
|
||||
* isn't present in the aperture, but various caches may
|
||||
* not be consistent.
|
||||
*/
|
||||
|
||||
void drm_ttm_evict(struct drm_ttm *ttm)
|
||||
{
|
||||
struct drm_ttm_backend *be = ttm->be;
|
||||
|
|
@ -356,17 +387,33 @@ void drm_ttm_evict(struct drm_ttm *ttm)
|
|||
ttm->state = ttm_evicted;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_ttm_fixup_caching:
|
||||
*
|
||||
* @ttm: the object to set unbound
|
||||
*
|
||||
* XXX this function is misnamed. Transition a ttm from evicted to
|
||||
* unbound, flushing caches as appropriate.
|
||||
*/
|
||||
void drm_ttm_fixup_caching(struct drm_ttm *ttm)
|
||||
{
|
||||
|
||||
if (ttm->state == ttm_evicted) {
|
||||
struct drm_ttm_backend *be = ttm->be;
|
||||
if (be->func->needs_ub_cache_adjust(be))
|
||||
drm_set_caching(ttm, 0);
|
||||
drm_ttm_set_caching(ttm, 0);
|
||||
ttm->state = ttm_unbound;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_ttm_unbind:
|
||||
*
|
||||
* @ttm: the object to unbind from the graphics device
|
||||
*
|
||||
* Unbind an object from the aperture. This removes the mappings
|
||||
* from the graphics device and flushes caches if necessary.
|
||||
*/
|
||||
void drm_ttm_unbind(struct drm_ttm *ttm)
|
||||
{
|
||||
if (ttm->state == ttm_bound)
|
||||
|
|
@ -375,7 +422,19 @@ void drm_ttm_unbind(struct drm_ttm *ttm)
|
|||
drm_ttm_fixup_caching(ttm);
|
||||
}
|
||||
|
||||
int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem)
|
||||
/**
|
||||
* drm_ttm_bind:
|
||||
*
|
||||
* @ttm: the ttm object to bind to the graphics device
|
||||
*
|
||||
* @bo_mem: the aperture memory region which will hold the object
|
||||
*
|
||||
* Bind a ttm object to the aperture. This ensures that the necessary
|
||||
* pages are allocated, flushes CPU caches as needed and marks the
|
||||
* ttm as DRM_TTM_PAGE_USER_DIRTY to indicate that it may have been
|
||||
* modified by the GPU
|
||||
*/
|
||||
int drm_ttm_bind(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem)
|
||||
{
|
||||
struct drm_bo_driver *bo_driver = ttm->dev->driver->bo_driver;
|
||||
int ret = 0;
|
||||
|
|
@ -393,7 +452,7 @@ int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem)
|
|||
return ret;
|
||||
|
||||
if (ttm->state == ttm_unbound && !(bo_mem->flags & DRM_BO_FLAG_CACHED))
|
||||
drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED);
|
||||
drm_ttm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED);
|
||||
else if ((bo_mem->flags & DRM_BO_FLAG_CACHED_MAPPED) &&
|
||||
bo_driver->ttm_cache_flush)
|
||||
bo_driver->ttm_cache_flush(ttm);
|
||||
|
|
@ -410,4 +469,4 @@ int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem)
|
|||
ttm->page_flags |= DRM_TTM_PAGE_USER_DIRTY;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_bind_ttm);
|
||||
EXPORT_SYMBOL(drm_ttm_bind);
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
|
|||
return NOPAGE_SIGBUS;
|
||||
get_page(page);
|
||||
|
||||
DRM_DEBUG("shm_nopage 0x%lx\n", address);
|
||||
DRM_DEBUG("0x%lx\n", address);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
|
|||
|
||||
get_page(page);
|
||||
|
||||
DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
|
||||
DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
@ -751,10 +751,10 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
|
|||
*/
|
||||
|
||||
if (!(bo->mem.flags & DRM_BO_FLAG_MAPPABLE)) {
|
||||
uint32_t new_mask = bo->mem.mask |
|
||||
uint32_t new_flags = bo->mem.proposed_flags |
|
||||
DRM_BO_FLAG_MAPPABLE |
|
||||
DRM_BO_FLAG_FORCE_MAPPABLE;
|
||||
err = drm_bo_move_buffer(bo, new_mask, 0, 0);
|
||||
err = drm_bo_move_buffer(bo, new_flags, 0, 0);
|
||||
if (err) {
|
||||
ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT;
|
||||
goto out_unlock;
|
||||
|
|
|
|||
|
|
@ -589,7 +589,7 @@ static void i810EmitState(struct drm_device * dev)
|
|||
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
|
||||
DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
|
||||
DRM_DEBUG("%x\n", dirty);
|
||||
|
||||
if (dirty & I810_UPLOAD_BUFFERS) {
|
||||
i810EmitDestVerified(dev, sarea_priv->BufferState);
|
||||
|
|
@ -821,8 +821,7 @@ static void i810_dma_dispatch_flip(struct drm_device * dev)
|
|||
int pitch = dev_priv->pitch;
|
||||
RING_LOCALS;
|
||||
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("page=%d pfCurrentPage=%d\n",
|
||||
dev_priv->current_page,
|
||||
dev_priv->sarea_priv->pf_current_page);
|
||||
|
||||
|
|
@ -867,8 +866,6 @@ static void i810_dma_quiescent(struct drm_device * dev)
|
|||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
/* printk("%s\n", __FUNCTION__); */
|
||||
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
|
|
@ -888,8 +885,6 @@ static int i810_flush_queue(struct drm_device * dev)
|
|||
int i, ret = 0;
|
||||
RING_LOCALS;
|
||||
|
||||
/* printk("%s\n", __FUNCTION__); */
|
||||
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
BEGIN_LP_RING(2);
|
||||
|
|
@ -968,7 +963,7 @@ static int i810_dma_vertex(struct drm_device *dev, void *data,
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
|
||||
DRM_DEBUG("idx %d used %d discard %d\n",
|
||||
vertex->idx, vertex->used, vertex->discard);
|
||||
|
||||
if (vertex->idx < 0 || vertex->idx > dma->buf_count)
|
||||
|
|
@ -1006,7 +1001,7 @@ static int i810_clear_bufs(struct drm_device *dev, void *data,
|
|||
static int i810_swap_bufs(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
DRM_DEBUG("i810_swap_bufs\n");
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1087,11 +1082,10 @@ static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf,
|
|||
|
||||
sarea_priv->dirty = 0x7f;
|
||||
|
||||
DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n", address, used);
|
||||
DRM_DEBUG("addr 0x%lx, used 0x%x\n", address, used);
|
||||
|
||||
dev_priv->counter++;
|
||||
DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
|
||||
DRM_DEBUG("i810_dma_dispatch_mc\n");
|
||||
DRM_DEBUG("start : %lx\n", start);
|
||||
DRM_DEBUG("used : %d\n", used);
|
||||
DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
|
||||
|
|
@ -1197,7 +1191,7 @@ static void i810_do_init_pageflip(struct drm_device * dev)
|
|||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
dev_priv->page_flipping = 1;
|
||||
dev_priv->current_page = 0;
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
|
|
@ -1207,7 +1201,7 @@ static int i810_do_cleanup_pageflip(struct drm_device * dev)
|
|||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
if (dev_priv->current_page != 0)
|
||||
i810_dma_dispatch_flip(dev);
|
||||
|
||||
|
|
@ -1220,7 +1214,7 @@ static int i810_flip_bufs(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ extern int i810_max_ioctl;
|
|||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__);\
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d)\n", n); \
|
||||
if (dev_priv->ring.space < n*4) \
|
||||
i810_wait_ring(dev, n*4); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev)
|
|||
return drm_agp_init_ttm(dev);
|
||||
}
|
||||
|
||||
int i915_fence_types(struct drm_buffer_object *bo,
|
||||
int i915_fence_type(struct drm_buffer_object *bo,
|
||||
uint32_t *fclass,
|
||||
uint32_t *type)
|
||||
{
|
||||
if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
|
||||
if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
|
||||
*type = 3;
|
||||
else
|
||||
*type = 1;
|
||||
|
|
@ -113,7 +113,16 @@ int i915_init_mem_type(struct drm_device *dev, uint32_t type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i915_evict_mask(struct drm_buffer_object *bo)
|
||||
/*
|
||||
* i915_evict_flags:
|
||||
*
|
||||
* @bo: the buffer object to be evicted
|
||||
*
|
||||
* Return the bo flags for a buffer which is not mapped to the hardware.
|
||||
* These will be placed in proposed_flags so that when the move is
|
||||
* finished, they'll end up in bo->mem.flags
|
||||
*/
|
||||
uint64_t i915_evict_flags(struct drm_buffer_object *bo)
|
||||
{
|
||||
switch (bo->mem.mem_type) {
|
||||
case DRM_BO_MEM_LOCAL:
|
||||
|
|
@ -280,7 +289,18 @@ void i915_flush_ttm(struct drm_ttm *ttm)
|
|||
return;
|
||||
|
||||
DRM_MEMORYBARRIER();
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/* Hopefully nobody has built an x86-64 processor without clflush */
|
||||
if (!cpu_has_clflush) {
|
||||
wbinvd();
|
||||
DRM_MEMORYBARRIER();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = ttm->num_pages - 1; i >= 0; i--)
|
||||
drm_cache_flush_page(drm_ttm_get_page(ttm, i));
|
||||
|
||||
DRM_MEMORYBARRIER();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,13 @@
|
|||
#define I915_IFPADDR 0x60
|
||||
#define I965_IFPADDR 0x70
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
|
||||
#define upper_32_bits(_val) (((u64)(_val)) >> 32)
|
||||
#endif
|
||||
|
||||
static struct _i9xx_private_compat {
|
||||
void __iomem *flush_page;
|
||||
int resource_valid;
|
||||
struct resource ifp_resource;
|
||||
} i9xx_private;
|
||||
|
||||
|
|
@ -57,16 +62,17 @@ static void intel_i915_setup_chipset_flush(struct pci_dev *pdev)
|
|||
pci_read_config_dword(pdev, I915_IFPADDR, &temp);
|
||||
if (!(temp & 0x1)) {
|
||||
intel_alloc_chipset_flush_resource(pdev);
|
||||
|
||||
i9xx_private.resource_valid = 1;
|
||||
pci_write_config_dword(pdev, I915_IFPADDR, (i9xx_private.ifp_resource.start & 0xffffffff) | 0x1);
|
||||
} else {
|
||||
temp &= ~1;
|
||||
|
||||
i9xx_private.resource_valid = 1;
|
||||
i9xx_private.ifp_resource.start = temp;
|
||||
i9xx_private.ifp_resource.end = temp + PAGE_SIZE;
|
||||
ret = request_resource(&iomem_resource, &i9xx_private.ifp_resource);
|
||||
if (ret) {
|
||||
i9xx_private.ifp_resource.start = 0;
|
||||
i9xx_private.resource_valid = 0;
|
||||
printk("Failed inserting resource into tree\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -84,6 +90,7 @@ static void intel_i965_g33_setup_chipset_flush(struct pci_dev *pdev)
|
|||
|
||||
intel_alloc_chipset_flush_resource(pdev);
|
||||
|
||||
i9xx_private.resource_valid = 1;
|
||||
pci_write_config_dword(pdev, I965_IFPADDR + 4,
|
||||
upper_32_bits(i9xx_private.ifp_resource.start));
|
||||
pci_write_config_dword(pdev, I965_IFPADDR, (i9xx_private.ifp_resource.start & 0xffffffff) | 0x1);
|
||||
|
|
@ -93,11 +100,12 @@ static void intel_i965_g33_setup_chipset_flush(struct pci_dev *pdev)
|
|||
temp_lo &= ~0x1;
|
||||
l64 = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
||||
i9xx_private.resource_valid = 1;
|
||||
i9xx_private.ifp_resource.start = l64;
|
||||
i9xx_private.ifp_resource.end = l64 + PAGE_SIZE;
|
||||
ret = request_resource(&iomem_resource, &i9xx_private.ifp_resource);
|
||||
if (!ret) {
|
||||
i9xx_private.ifp_resource.start = 0;
|
||||
if (ret) {
|
||||
i9xx_private.resource_valid = 0;
|
||||
printk("Failed inserting resource into tree\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +175,9 @@ static void intel_i9xx_setup_flush(struct drm_device *dev)
|
|||
static void intel_i9xx_fini_flush(struct drm_device *dev)
|
||||
{
|
||||
iounmap(i9xx_private.flush_page);
|
||||
release_resource(&i9xx_private.ifp_resource);
|
||||
if (i9xx_private.resource_valid)
|
||||
release_resource(&i9xx_private.ifp_resource);
|
||||
i9xx_private.resource_valid = 0;
|
||||
}
|
||||
|
||||
static void intel_i9xx_flush_page(struct drm_device *dev)
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ static struct drm_bo_driver i915_bo_driver = {
|
|||
.num_mem_type_prio = sizeof(i915_mem_prios)/sizeof(uint32_t),
|
||||
.num_mem_busy_prio = sizeof(i915_busy_prios)/sizeof(uint32_t),
|
||||
.create_ttm_backend_entry = i915_create_ttm_backend_entry,
|
||||
.fence_type = i915_fence_types,
|
||||
.fence_type = i915_fence_type,
|
||||
.invalidate_caches = i915_invalidate_caches,
|
||||
.init_mem_type = i915_init_mem_type,
|
||||
.evict_mask = i915_evict_mask,
|
||||
.evict_flags = i915_evict_flags,
|
||||
.move = i915_move,
|
||||
.ttm_cache_flush = i915_flush_ttm,
|
||||
};
|
||||
|
|
@ -331,7 +331,7 @@ static int i915_suspend(struct drm_device *dev)
|
|||
dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
|
||||
dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
|
||||
dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
|
||||
if (IS_I965GM(dev)) {
|
||||
if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
|
||||
dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
|
||||
dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
|
||||
}
|
||||
|
|
@ -537,8 +537,7 @@ static struct drm_driver driver = {
|
|||
*/
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR | */
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
|
||||
DRIVER_IRQ_VBL2,
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.load = i915_driver_load,
|
||||
.unload = i915_driver_unload,
|
||||
/* .lastclose = i915_driver_lastclose,
|
||||
|
|
@ -546,8 +545,9 @@ static struct drm_driver driver = {
|
|||
.suspend = i915_suspend,
|
||||
.resume = i915_resume,
|
||||
.device_is_agp = i915_driver_device_is_agp,
|
||||
.vblank_wait = i915_driver_vblank_wait,
|
||||
.vblank_wait2 = i915_driver_vblank_wait2,
|
||||
.get_vblank_counter = i915_get_vblank_counter,
|
||||
.enable_vblank = i915_enable_vblank,
|
||||
.disable_vblank = i915_disable_vblank,
|
||||
.irq_preinstall = i915_driver_irq_preinstall,
|
||||
.irq_postinstall = i915_driver_irq_postinstall,
|
||||
.irq_uninstall = i915_driver_irq_uninstall,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
typedef struct _drm_i915_batchbuffer32 {
|
||||
int start; /* agp offset */
|
||||
|
|
@ -182,13 +183,73 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
|
|||
DRM_IOCTL_I915_ALLOC, (unsigned long) request);
|
||||
}
|
||||
|
||||
typedef struct drm_i915_execbuffer32 {
|
||||
uint64_t ops_list;
|
||||
uint32_t num_buffers;
|
||||
struct _drm_i915_batchbuffer32 batch;
|
||||
drm_context_t context;
|
||||
struct drm_fence_arg fence_arg;
|
||||
} drm_i915_execbuffer32_t;
|
||||
|
||||
static int compat_i915_execbuffer(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_execbuffer32_t req32;
|
||||
struct drm_i915_execbuffer __user *request;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
|
||||
return -EFAULT;
|
||||
|
||||
request = compat_alloc_user_space(sizeof(*request));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|
||||
|| __put_user(req32.ops_list, &request->ops_list)
|
||||
|| __put_user(req32.num_buffers, &request->num_buffers)
|
||||
|| __put_user(req32.context, &request->context)
|
||||
|| __copy_to_user(&request->fence_arg, &req32.fence_arg,
|
||||
sizeof(req32.fence_arg))
|
||||
|| __put_user(req32.batch.start, &request->batch.start)
|
||||
|| __put_user(req32.batch.used, &request->batch.used)
|
||||
|| __put_user(req32.batch.DR1, &request->batch.DR1)
|
||||
|| __put_user(req32.batch.DR4, &request->batch.DR4)
|
||||
|| __put_user(req32.batch.num_cliprects,
|
||||
&request->batch.num_cliprects)
|
||||
|| __put_user((int __user *)(unsigned long)req32.batch.cliprects,
|
||||
&request->batch.cliprects))
|
||||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_EXECBUFFER, (unsigned long)request);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (__get_user(req32.fence_arg.handle, &request->fence_arg.handle)
|
||||
|| __get_user(req32.fence_arg.fence_class, &request->fence_arg.fence_class)
|
||||
|| __get_user(req32.fence_arg.type, &request->fence_arg.type)
|
||||
|| __get_user(req32.fence_arg.flags, &request->fence_arg.flags)
|
||||
|| __get_user(req32.fence_arg.signaled, &request->fence_arg.signaled)
|
||||
|| __get_user(req32.fence_arg.error, &request->fence_arg.error)
|
||||
|| __get_user(req32.fence_arg.sequence, &request->fence_arg.sequence))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &req32, sizeof(req32)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
drm_ioctl_compat_t *i915_compat_ioctls[] = {
|
||||
[DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
|
||||
[DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
|
||||
[DRM_I915_GETPARAM] = compat_i915_getparam,
|
||||
[DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
|
||||
[DRM_I915_ALLOC] = compat_i915_alloc
|
||||
[DRM_I915_ALLOC] = compat_i915_alloc,
|
||||
#ifdef I915_HAVE_BUFFER
|
||||
[DRM_I915_EXECBUFFER] = compat_i915_execbuffer,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
|||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA
|
||||
| DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
|
||||
| DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.lastclose = mach64_driver_lastclose,
|
||||
.vblank_wait = mach64_driver_vblank_wait,
|
||||
.get_vblank_counter = mach64_get_vblank_counter,
|
||||
.enable_vblank = mach64_enable_vblank,
|
||||
.disable_vblank = mach64_disable_vblank,
|
||||
.irq_preinstall = mach64_driver_irq_preinstall,
|
||||
.irq_postinstall = mach64_driver_irq_postinstall,
|
||||
.irq_uninstall = mach64_driver_irq_uninstall,
|
||||
|
|
|
|||
|
|
@ -46,15 +46,16 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
|||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL,
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.dev_priv_size = sizeof (drm_mga_buf_priv_t),
|
||||
.load = mga_driver_load,
|
||||
.unload = mga_driver_unload,
|
||||
.lastclose = mga_driver_lastclose,
|
||||
.dma_quiescent = mga_driver_dma_quiescent,
|
||||
.device_is_agp = mga_driver_device_is_agp,
|
||||
.vblank_wait = mga_driver_vblank_wait,
|
||||
.get_vblank_counter = mga_get_vblank_counter,
|
||||
.enable_vblank = mga_enable_vblank,
|
||||
.disable_vblank = mga_disable_vblank,
|
||||
.irq_preinstall = mga_driver_irq_preinstall,
|
||||
.irq_postinstall = mga_driver_irq_postinstall,
|
||||
.irq_uninstall = mga_driver_irq_uninstall,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ nouveau_bo_fence_type(struct drm_buffer_object *bo,
|
|||
{
|
||||
/* When we get called, *fclass is set to the requested fence class */
|
||||
|
||||
if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
|
||||
if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
|
||||
*type = 3;
|
||||
else
|
||||
*type = 1;
|
||||
|
|
@ -130,8 +130,8 @@ nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
nouveau_bo_evict_mask(struct drm_buffer_object *bo)
|
||||
static uint64_t
|
||||
nouveau_bo_evict_flags(struct drm_buffer_object *bo)
|
||||
{
|
||||
switch (bo->mem.mem_type) {
|
||||
case DRM_BO_MEM_LOCAL:
|
||||
|
|
@ -207,15 +207,16 @@ nouveau_bo_move_gart(struct drm_buffer_object *bo, int evict, int no_wait,
|
|||
|
||||
tmp_mem = *new_mem;
|
||||
tmp_mem.mm_node = NULL;
|
||||
tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
|
||||
DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING;
|
||||
tmp_mem.proposed_flags = (DRM_BO_FLAG_MEM_TT |
|
||||
DRM_BO_FLAG_CACHED |
|
||||
DRM_BO_FLAG_FORCE_CACHING);
|
||||
|
||||
ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_bind_ttm(bo->ttm, &tmp_mem);
|
||||
ret = drm_ttm_bind (bo->ttm, &tmp_mem);
|
||||
if (ret)
|
||||
goto out_cleanup;
|
||||
|
||||
|
|
@ -291,7 +292,7 @@ struct drm_bo_driver nouveau_bo_driver = {
|
|||
.fence_type = nouveau_bo_fence_type,
|
||||
.invalidate_caches = nouveau_bo_invalidate_caches,
|
||||
.init_mem_type = nouveau_bo_init_mem_type,
|
||||
.evict_mask = nouveau_bo_evict_mask,
|
||||
.evict_flags = nouveau_bo_evict_flags,
|
||||
.move = nouveau_bo_move,
|
||||
.ttm_cache_flush= nouveau_bo_flush_ttm
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
|
|||
|
||||
static int
|
||||
nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
|
||||
struct page **pages)
|
||||
struct page **pages, struct page *dummy_read_page)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
int p, d, o;
|
||||
|
|
@ -41,8 +41,11 @@ nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
|
|||
nvbe->pages_populated = d = 0;
|
||||
for (p = 0; p < num_pages; p++) {
|
||||
for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
|
||||
struct page *page = pages[p];
|
||||
if (!page)
|
||||
page = dummy_read_page;
|
||||
nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
|
||||
pages[p], o,
|
||||
page, o,
|
||||
NV_CTXDMA_PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(nvbe->pagelist[d])) {
|
||||
|
|
@ -136,8 +139,8 @@ nouveau_sgdma_unbind(struct drm_ttm_backend *be)
|
|||
if (dev_priv->card_type < NV_50) {
|
||||
INSTANCE_WR(gpuobj, pte, pteval | 3);
|
||||
} else {
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+0, 0x00000010);
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000004);
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+0, pteval | 0x21);
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000000);
|
||||
}
|
||||
|
||||
pte++;
|
||||
|
|
@ -218,15 +221,14 @@ nouveau_sgdma_init(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
dev_priv->gart_info.sg_dummy_page =
|
||||
alloc_page(GFP_KERNEL|__GFP_DMA32);
|
||||
SetPageLocked(dev_priv->gart_info.sg_dummy_page);
|
||||
dev_priv->gart_info.sg_dummy_bus =
|
||||
pci_map_page(dev->pdev,
|
||||
dev_priv->gart_info.sg_dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
dev_priv->gart_info.sg_dummy_page =
|
||||
alloc_page(GFP_KERNEL|__GFP_DMA32);
|
||||
SetPageLocked(dev_priv->gart_info.sg_dummy_page);
|
||||
dev_priv->gart_info.sg_dummy_bus =
|
||||
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
|
||||
* confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
|
||||
* on those cards? */
|
||||
|
|
@ -242,8 +244,9 @@ nouveau_sgdma_init(struct drm_device *dev)
|
|||
}
|
||||
} else {
|
||||
for (i=0; i<obj_size; i+=8) {
|
||||
INSTANCE_WR(gpuobj, (i+0)/4, 0); //x00000010);
|
||||
INSTANCE_WR(gpuobj, (i+4)/4, 0); //0x00000004);
|
||||
INSTANCE_WR(gpuobj, (i+0)/4,
|
||||
dev_priv->gart_info.sg_dummy_bus | 0x21);
|
||||
INSTANCE_WR(gpuobj, (i+4)/4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +302,7 @@ nouveau_sgdma_nottm_hack_init(struct drm_device *dev)
|
|||
}
|
||||
dev_priv->gart_info.sg_handle = sgreq.handle;
|
||||
|
||||
if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist))) {
|
||||
if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist, dev->bm.dummy_read_page))) {
|
||||
DRM_ERROR("failed populate: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,13 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
|||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL,
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
|
||||
.preclose = r128_driver_preclose,
|
||||
.lastclose = r128_driver_lastclose,
|
||||
.vblank_wait = r128_driver_vblank_wait,
|
||||
.get_vblank_counter = r128_get_vblank_counter,
|
||||
.enable_vblank = r128_enable_vblank,
|
||||
.disable_vblank = r128_disable_vblank,
|
||||
.irq_preinstall = r128_driver_irq_preinstall,
|
||||
.irq_postinstall = r128_driver_irq_postinstall,
|
||||
.irq_uninstall = r128_driver_irq_uninstall,
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int radeon_invalidate_caches(struct drm_device * dev, uint64_t flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t radeon_evict_mask(struct drm_buffer_object *bo)
|
||||
uint64_t radeon_evict_flags(struct drm_buffer_object *bo)
|
||||
{
|
||||
switch (bo->mem.mem_type) {
|
||||
case DRM_BO_MEM_LOCAL:
|
||||
|
|
@ -216,14 +216,14 @@ static int radeon_move_flip(struct drm_buffer_object * bo,
|
|||
|
||||
tmp_mem = *new_mem;
|
||||
tmp_mem.mm_node = NULL;
|
||||
tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
|
||||
tmp_mem.flags = DRM_BO_FLAG_MEM_TT |
|
||||
DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING;
|
||||
|
||||
ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_bind_ttm(bo->ttm, &tmp_mem);
|
||||
ret = drm_ttm_bind(bo->ttm, &tmp_mem);
|
||||
if (ret)
|
||||
goto out_cleanup;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ static struct drm_bo_driver radeon_bo_driver = {
|
|||
.fence_type = radeon_fence_types,
|
||||
.invalidate_caches = radeon_invalidate_caches,
|
||||
.init_mem_type = radeon_init_mem_type,
|
||||
.evict_mask = radeon_evict_mask,
|
||||
.evict_flags = radeon_evict_flags,
|
||||
.move = radeon_move,
|
||||
};
|
||||
#endif
|
||||
|
|
@ -92,8 +92,7 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
|||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
|
||||
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
|
||||
.load = radeon_driver_load,
|
||||
.firstopen = radeon_driver_firstopen,
|
||||
|
|
@ -102,8 +101,9 @@ static struct drm_driver driver = {
|
|||
.postclose = radeon_driver_postclose,
|
||||
.lastclose = radeon_driver_lastclose,
|
||||
.unload = radeon_driver_unload,
|
||||
.vblank_wait = radeon_driver_vblank_wait,
|
||||
.vblank_wait2 = radeon_driver_vblank_wait2,
|
||||
.get_vblank_counter = radeon_get_vblank_counter,
|
||||
.enable_vblank = radeon_enable_vblank,
|
||||
.disable_vblank = radeon_disable_vblank,
|
||||
.dri_library_name = dri_library_name,
|
||||
.irq_preinstall = radeon_driver_irq_preinstall,
|
||||
.irq_postinstall = radeon_driver_irq_postinstall,
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ static struct drm_driver driver = {
|
|||
.context_dtor = NULL,
|
||||
.kernel_context_switch = NULL,
|
||||
.kernel_context_switch_unlock = NULL,
|
||||
.vblank_wait = NULL,
|
||||
.vblank_wait2 = NULL,
|
||||
.dri_library_name = radeon_ms_driver_dri_library_name,
|
||||
.device_is_agp = NULL,
|
||||
.irq_handler = radeon_ms_irq_handler,
|
||||
|
|
@ -83,8 +81,7 @@ static struct drm_driver driver = {
|
|||
.date = DRIVER_DATE,
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
|
||||
.dev_priv_size = 0,
|
||||
.ioctls = radeon_ms_ioctls,
|
||||
.num_ioctls = 0,
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file
|
|||
dev_priv->vram_offset = fb->offset;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
|
||||
DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
|
|||
dev_priv->agp_offset = agp->offset;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
|
||||
DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ int via_init_mem_type(struct drm_device * dev, uint32_t type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t via_evict_mask(struct drm_buffer_object *bo)
|
||||
uint64_t via_evict_flags(struct drm_buffer_object *bo)
|
||||
{
|
||||
switch (bo->mem.mem_type) {
|
||||
case DRM_BO_MEM_LOCAL:
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
dev_priv->agp_offset = agp->offset;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
|
||||
DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
dev_priv->vram_offset = fb->offset;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
|
||||
DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -555,6 +555,21 @@ union drm_wait_vblank {
|
|||
struct drm_wait_vblank_reply reply;
|
||||
};
|
||||
|
||||
enum drm_modeset_ctl_cmd {
|
||||
_DRM_PRE_MODESET = 1,
|
||||
_DRM_POST_MODESET = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MODESET_CTL ioctl argument type
|
||||
*
|
||||
* \sa drmModesetCtl().
|
||||
*/
|
||||
struct drm_modeset_ctl {
|
||||
unsigned long arg;
|
||||
enum drm_modeset_ctl_cmd cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
|
||||
*
|
||||
|
|
@ -661,6 +676,10 @@ struct drm_fence_arg {
|
|||
#define DRM_BO_FLAG_WRITE (1ULL << 1)
|
||||
#define DRM_BO_FLAG_EXE (1ULL << 2)
|
||||
|
||||
/*
|
||||
* All of the bits related to access mode
|
||||
*/
|
||||
#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE)
|
||||
/*
|
||||
* Status flags. Can be read to determine the actual state of a buffer.
|
||||
* Can also be set in the buffer mask before validation.
|
||||
|
|
@ -701,7 +720,14 @@ struct drm_fence_arg {
|
|||
*/
|
||||
#define DRM_BO_FLAG_NO_MOVE (1ULL << 8)
|
||||
|
||||
/* Mask: Make sure the buffer is in cached memory when mapped
|
||||
/* Mask: Make sure the buffer is in cached memory when mapped. In conjunction
|
||||
* with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART
|
||||
* with unsnooped PTEs instead of snooped, by using chipset-specific cache
|
||||
* flushing at bind time. A better name might be DRM_BO_FLAG_TT_UNSNOOPED,
|
||||
* as the eviction to local memory (TTM unbind) on map is just a side effect
|
||||
* to prevent aggressive cache prefetch from the GPU disturbing the cache
|
||||
* management that the DRM is doing.
|
||||
*
|
||||
* Flags: Acknowledge.
|
||||
* Buffers allocated with this flag should not be used for suballocators
|
||||
* This type may have issues on CPUs with over-aggressive caching
|
||||
|
|
@ -741,18 +767,49 @@ struct drm_fence_arg {
|
|||
#define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31)
|
||||
/* We can add more of these now with a 64-bit flag type */
|
||||
|
||||
/* Memory flag mask */
|
||||
/*
|
||||
* This is a mask covering all of the memory type flags; easier to just
|
||||
* use a single constant than a bunch of | values. It covers
|
||||
* DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4
|
||||
*/
|
||||
#define DRM_BO_MASK_MEM 0x00000000FF000000ULL
|
||||
#define DRM_BO_MASK_MEMTYPE 0x00000000FF0800A0ULL
|
||||
|
||||
/*
|
||||
* This adds all of the CPU-mapping options in with the memory
|
||||
* type to label all bits which change how the page gets mapped
|
||||
*/
|
||||
#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \
|
||||
DRM_BO_FLAG_CACHED_MAPPED | \
|
||||
DRM_BO_FLAG_CACHED | \
|
||||
DRM_BO_FLAG_MAPPABLE)
|
||||
|
||||
/* Driver-private flags */
|
||||
#define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL
|
||||
|
||||
/* Don't block on validate and map */
|
||||
/*
|
||||
* Don't block on validate and map. Instead, return EBUSY.
|
||||
*/
|
||||
#define DRM_BO_HINT_DONT_BLOCK 0x00000002
|
||||
/* Don't place this buffer on the unfenced list.*/
|
||||
/*
|
||||
* Don't place this buffer on the unfenced list. This means
|
||||
* that the buffer will not end up having a fence associated
|
||||
* with it as a result of this operation
|
||||
*/
|
||||
#define DRM_BO_HINT_DONT_FENCE 0x00000004
|
||||
/*
|
||||
* Sleep while waiting for the operation to complete.
|
||||
* Without this flag, the kernel will, instead, spin
|
||||
* until this operation has completed. I'm not sure
|
||||
* why you would ever want this, so please always
|
||||
* provide DRM_BO_HINT_WAIT_LAZY to any operation
|
||||
* which may block
|
||||
*/
|
||||
#define DRM_BO_HINT_WAIT_LAZY 0x00000008
|
||||
/*
|
||||
* The client has compute relocations refering to this buffer using the
|
||||
* offset in the presumed_offset field. If that offset ends up matching
|
||||
* where this buffer lands, the kernel is free to skip executing those
|
||||
* relocations
|
||||
*/
|
||||
#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010
|
||||
|
||||
#define DRM_BO_INIT_MAGIC 0xfe769812
|
||||
|
|
@ -774,7 +831,7 @@ struct drm_bo_info_req {
|
|||
};
|
||||
|
||||
struct drm_bo_create_req {
|
||||
uint64_t mask;
|
||||
uint64_t flags;
|
||||
uint64_t size;
|
||||
uint64_t buffer_start;
|
||||
unsigned int hint;
|
||||
|
|
@ -790,7 +847,7 @@ struct drm_bo_create_req {
|
|||
|
||||
struct drm_bo_info_rep {
|
||||
uint64_t flags;
|
||||
uint64_t mask;
|
||||
uint64_t proposed_flags;
|
||||
uint64_t size;
|
||||
uint64_t offset;
|
||||
uint64_t arg_handle;
|
||||
|
|
@ -1046,6 +1103,7 @@ struct drm_mode_mode_cmd {
|
|||
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
|
||||
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
|
||||
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
|
||||
#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
|
||||
|
||||
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
|
||||
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
|
||||
|
|
@ -1118,7 +1176,6 @@ struct drm_mode_mode_cmd {
|
|||
#define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
|
||||
#define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg)
|
||||
|
||||
|
||||
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
|
||||
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output)
|
||||
|
|
@ -1133,6 +1190,7 @@ struct drm_mode_mode_cmd {
|
|||
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property)
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -139,6 +139,101 @@
|
|||
0x1002 0x5e4c CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE"
|
||||
0x1002 0x5e4d CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700"
|
||||
0x1002 0x5e4f CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE"
|
||||
0x1002 0x7100 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x7101 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1800 XT"
|
||||
0x1002 0x7102 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1800"
|
||||
0x1002 0x7103 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V7200"
|
||||
0x1002 0x7104 CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7200"
|
||||
0x1002 0x7105 CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V5300"
|
||||
0x1002 0x7106 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V7100"
|
||||
0x1002 0x7108 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x7109 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x710A CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x710B CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x710C CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800"
|
||||
0x1002 0x710E CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7300"
|
||||
0x1002 0x710F CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7350"
|
||||
0x1002 0x7140 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x7141 CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505"
|
||||
0x1002 0x7142 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550"
|
||||
0x1002 0x7143 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550"
|
||||
0x1002 0x7144 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI M54-GL"
|
||||
0x1002 0x7145 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1400"
|
||||
0x1002 0x7146 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550"
|
||||
0x1002 0x7147 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit"
|
||||
0x1002 0x7149 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300"
|
||||
0x1002 0x714A CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300"
|
||||
0x1002 0x714B CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300"
|
||||
0x1002 0x714C CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300"
|
||||
0x1002 0x714D CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300"
|
||||
0x1002 0x714E CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300"
|
||||
0x1002 0x714F CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505"
|
||||
0x1002 0x7151 CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505"
|
||||
0x1002 0x7152 CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireGL V3300"
|
||||
0x1002 0x7153 CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireGL V3350"
|
||||
0x1002 0x715E CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300"
|
||||
0x1002 0x715F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit"
|
||||
0x1002 0x7180 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550"
|
||||
0x1002 0x7181 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x7183 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550"
|
||||
0x1002 0x7186 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1450"
|
||||
0x1002 0x7187 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550"
|
||||
0x1002 0x7188 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X2300"
|
||||
0x1002 0x718A CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X2300"
|
||||
0x1002 0x718B CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350"
|
||||
0x1002 0x718C CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350"
|
||||
0x1002 0x718D CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1450"
|
||||
0x1002 0x718F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300"
|
||||
0x1002 0x7193 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550"
|
||||
0x1002 0x7196 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350"
|
||||
0x1002 0x719B CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireMV 2250"
|
||||
0x1002 0x719F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit"
|
||||
0x1002 0x71C0 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x71C1 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650"
|
||||
0x1002 0x71C2 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x71C3 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x71C4 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5200"
|
||||
0x1002 0x71C5 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1600"
|
||||
0x1002 0x71C6 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650"
|
||||
0x1002 0x71C7 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650"
|
||||
0x1002 0x71CD CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600"
|
||||
0x1002 0x71CE CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1300 XT/X1600 Pro"
|
||||
0x1002 0x71D2 CHIP_RV530|RADEON_NEW_MEMMAP "ATI FireGL V3400"
|
||||
0x1002 0x71D4 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5250"
|
||||
0x1002 0x71D5 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700"
|
||||
0x1002 0x71D6 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700 XT"
|
||||
0x1002 0x71DA CHIP_RV530|RADEON_NEW_MEMMAP "ATI FireGL V5200"
|
||||
0x1002 0x71DE CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700"
|
||||
0x1002 0x7200 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X2300HD"
|
||||
0x1002 0x7210 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon HD 2300"
|
||||
0x1002 0x7211 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon HD 2300"
|
||||
0x1002 0x7240 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1950"
|
||||
0x1002 0x7243 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7244 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1950"
|
||||
0x1002 0x7245 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7246 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7247 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7248 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7249 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x724A CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x724B CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x724C CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x724D CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x724E CHIP_R580|RADEON_NEW_MEMMAP "ATI AMD Stream Processor"
|
||||
0x1002 0x724F CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900"
|
||||
0x1002 0x7280 CHIP_RV570|RADEON_NEW_MEMMAP "ATI Radeon X1950"
|
||||
0x1002 0x7281 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560"
|
||||
0x1002 0x7283 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560"
|
||||
0x1002 0x7284 CHIP_R580|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1900"
|
||||
0x1002 0x7287 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560"
|
||||
0x1002 0x7288 CHIP_RV570|RADEON_NEW_MEMMAP "ATI Radeon X1950 GT"
|
||||
0x1002 0x7289 CHIP_RV570|RADEON_NEW_MEMMAP "ATI RV570"
|
||||
0x1002 0x728B CHIP_RV570|RADEON_NEW_MEMMAP "ATI RV570"
|
||||
0x1002 0x728C CHIP_RV570|RADEON_NEW_MEMMAP "ATI ATI FireGL V7400"
|
||||
0x1002 0x7290 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560"
|
||||
0x1002 0x7291 CHIP_RV560|RADEON_NEW_MEMMAP "ATI Radeon X1650"
|
||||
0x1002 0x7293 CHIP_RV560|RADEON_NEW_MEMMAP "ATI Radeon X1650"
|
||||
0x1002 0x7297 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560"
|
||||
0x1002 0x7834 CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP"
|
||||
0x1002 0x7835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP"
|
||||
|
||||
|
|
@ -236,6 +331,7 @@
|
|||
0x1106 0x3343 0 "VIA P4M890"
|
||||
0x1106 0x3230 VIA_DX9_0 "VIA K8M890"
|
||||
0x1106 0x3157 VIA_PRO_GROUP_A "VIA CX700"
|
||||
0x1106 0x3371 VIA_DX9_0 "VIA P4M900 / VN896"
|
||||
|
||||
[i810]
|
||||
0x8086 0x7121 0 "Intel i810 GMCH"
|
||||
|
|
@ -285,6 +381,7 @@
|
|||
0x8086 0x3582 CHIP_I8XX "Intel i852GM/i855GM GMCH"
|
||||
0x8086 0x2572 CHIP_I8XX "Intel i865G GMCH"
|
||||
0x8086 0x2582 CHIP_I9XX|CHIP_I915 "Intel i915G"
|
||||
0x8086 0x258a CHIP_I9XX|CHIP_I915 "Intel E7221 (i915)"
|
||||
0x8086 0x2592 CHIP_I9XX|CHIP_I915 "Intel i915GM"
|
||||
0x8086 0x2772 CHIP_I9XX|CHIP_I915 "Intel i945G"
|
||||
0x8086 0x27A2 CHIP_I9XX|CHIP_I915 "Intel i945GM"
|
||||
|
|
@ -298,6 +395,7 @@
|
|||
0x8086 0x29C2 CHIP_I9XX|CHIP_I915 "Intel G33"
|
||||
0x8086 0x29B2 CHIP_I9XX|CHIP_I915 "Intel Q35"
|
||||
0x8086 0x29D2 CHIP_I9XX|CHIP_I915 "Intel Q33"
|
||||
0x8086 0x2A42 CHIP_I9XX|CHIP_I965 "Intel Integrated Graphics Device"
|
||||
|
||||
[imagine]
|
||||
0x105d 0x2309 IMAGINE_128 "Imagine 128"
|
||||
|
|
|
|||
|
|
@ -718,9 +718,15 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
|
|||
unsigned index;
|
||||
unsigned long new_cmd_offset;
|
||||
u32 val;
|
||||
int ret;
|
||||
int ret, i;
|
||||
int buf_index = -1;
|
||||
|
||||
if (reloc[2] >= num_buffers) {
|
||||
for (i = 0; i <= num_buffers; i++)
|
||||
if (buffers[i].buffer)
|
||||
if (reloc[2] == buffers[i].buffer->base.hash.key)
|
||||
buf_index = i;
|
||||
|
||||
if (buf_index == -1) {
|
||||
DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -729,7 +735,7 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
|
|||
* Short-circuit relocations that were correctly
|
||||
* guessed by the client
|
||||
*/
|
||||
if (buffers[reloc[2]].presumed_offset_correct && !DRM_DEBUG_RELOCATION)
|
||||
if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION)
|
||||
return 0;
|
||||
|
||||
new_cmd_offset = reloc[0];
|
||||
|
|
@ -756,17 +762,17 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
|
|||
relocatee->page_offset = (relocatee->offset & PAGE_MASK);
|
||||
}
|
||||
|
||||
val = buffers[reloc[2]].buffer->offset;
|
||||
val = buffers[buf_index].buffer->offset;
|
||||
index = (reloc[0] - relocatee->page_offset) >> 2;
|
||||
|
||||
/* add in validate */
|
||||
val = val + reloc[1];
|
||||
|
||||
if (DRM_DEBUG_RELOCATION) {
|
||||
if (buffers[reloc[2]].presumed_offset_correct &&
|
||||
if (buffers[buf_index].presumed_offset_correct &&
|
||||
relocatee->data_page[index] != val) {
|
||||
DRM_DEBUG ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n",
|
||||
reloc[0], reloc[1], reloc[2], relocatee->data_page[index], val);
|
||||
reloc[0], reloc[1], buf_index, relocatee->data_page[index], val);
|
||||
}
|
||||
}
|
||||
relocatee->data_page[index] = val;
|
||||
|
|
@ -775,94 +781,79 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
|
|||
|
||||
int i915_process_relocs(struct drm_file *file_priv,
|
||||
uint32_t buf_handle,
|
||||
uint32_t *reloc_buf_handle,
|
||||
uint32_t __user **reloc_user_ptr,
|
||||
struct i915_relocatee_info *relocatee,
|
||||
struct drm_i915_validate_buffer *buffers,
|
||||
uint32_t num_buffers)
|
||||
{
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
struct drm_buffer_object *reloc_list_object;
|
||||
uint32_t cur_handle = *reloc_buf_handle;
|
||||
uint32_t *reloc_page;
|
||||
int ret, reloc_is_iomem, reloc_stride;
|
||||
uint32_t num_relocs, reloc_offset, reloc_end, reloc_page_offset, next_offset, cur_offset;
|
||||
struct drm_bo_kmap_obj reloc_kmap;
|
||||
int ret, reloc_stride;
|
||||
uint32_t cur_offset;
|
||||
uint32_t reloc_count;
|
||||
uint32_t reloc_type;
|
||||
uint32_t reloc_buf_size;
|
||||
uint32_t *reloc_buf = NULL;
|
||||
int i;
|
||||
|
||||
memset(&reloc_kmap, 0, sizeof(reloc_kmap));
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (!reloc_list_object)
|
||||
return -EINVAL;
|
||||
|
||||
ret = drm_bo_kmap(reloc_list_object, 0, 1, &reloc_kmap);
|
||||
/* do a copy from user from the user ptr */
|
||||
ret = get_user(reloc_count, *reloc_user_ptr);
|
||||
if (ret) {
|
||||
DRM_ERROR("Could not map relocation buffer.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
|
||||
num_relocs = reloc_page[0] & 0xffff;
|
||||
ret = get_user(reloc_type, (*reloc_user_ptr)+1);
|
||||
if (ret) {
|
||||
DRM_ERROR("Could not map relocation buffer.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((reloc_page[0] >> 16) & 0xffff) {
|
||||
if (reloc_type != 0) {
|
||||
DRM_ERROR("Unsupported relocation type requested\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
reloc_buf_size = (I915_RELOC_HEADER + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t);
|
||||
reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL);
|
||||
if (!reloc_buf) {
|
||||
DRM_ERROR("Out of memory for reloc buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get next relocate buffer handle */
|
||||
*reloc_buf_handle = reloc_page[1];
|
||||
*reloc_user_ptr = (uint32_t *)*(unsigned long *)&reloc_buf[2];
|
||||
|
||||
reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */
|
||||
|
||||
DRM_DEBUG("num relocs is %d, next is %08X\n", num_relocs, reloc_page[1]);
|
||||
DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, *reloc_user_ptr);
|
||||
|
||||
reloc_page_offset = 0;
|
||||
reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t);
|
||||
reloc_end = reloc_offset + (num_relocs * reloc_stride);
|
||||
for (i = 0; i < reloc_count; i++) {
|
||||
cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE);
|
||||
|
||||
ret = i915_apply_reloc(file_priv, num_buffers, buffers,
|
||||
relocatee, reloc_buf + cur_offset);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
next_offset = drm_bo_offset_end(reloc_offset, reloc_end);
|
||||
|
||||
do {
|
||||
cur_offset = ((reloc_offset + reloc_page_offset) & ~PAGE_MASK) / sizeof(uint32_t);
|
||||
ret = i915_apply_reloc(file_priv, num_buffers,
|
||||
buffers, relocatee, &reloc_page[cur_offset]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
reloc_offset += reloc_stride;
|
||||
} while (reloc_offset < next_offset);
|
||||
|
||||
drm_bo_kunmap(&reloc_kmap);
|
||||
|
||||
reloc_offset = next_offset;
|
||||
if (reloc_offset != reloc_end) {
|
||||
ret = drm_bo_kmap(reloc_list_object, reloc_offset >> PAGE_SHIFT, 1, &reloc_kmap);
|
||||
if (ret) {
|
||||
DRM_ERROR("Could not map relocation buffer.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
|
||||
reloc_page_offset = reloc_offset & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
} while (reloc_offset != reloc_end);
|
||||
out:
|
||||
|
||||
if (reloc_buf)
|
||||
kfree(reloc_buf);
|
||||
drm_bo_kunmap(&relocatee->kmap);
|
||||
relocatee->data_page = NULL;
|
||||
|
||||
drm_bo_kunmap(&reloc_kmap);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_bo_usage_deref_locked(&reloc_list_object);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
|
||||
drm_handle_t buf_reloc_handle,
|
||||
uint32_t __user *reloc_user_ptr,
|
||||
struct drm_i915_validate_buffer *buffers,
|
||||
uint32_t buf_count)
|
||||
{
|
||||
|
|
@ -896,8 +887,8 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
while (buf_reloc_handle) {
|
||||
ret = i915_process_relocs(file_priv, buf_handle, &buf_reloc_handle, &relocatee, buffers, buf_count);
|
||||
while (reloc_user_ptr) {
|
||||
ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count);
|
||||
if (ret) {
|
||||
DRM_ERROR("process relocs failed\n");
|
||||
break;
|
||||
|
|
@ -927,8 +918,8 @@ int i915_validate_buffer_list(struct drm_file *file_priv,
|
|||
int ret = 0;
|
||||
unsigned buf_count = 0;
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
uint32_t buf_reloc_handle, buf_handle;
|
||||
|
||||
uint32_t buf_handle;
|
||||
uint32_t __user *reloc_user_ptr;
|
||||
|
||||
do {
|
||||
if (buf_count >= *num_buffers) {
|
||||
|
|
@ -963,21 +954,19 @@ int i915_validate_buffer_list(struct drm_file *file_priv,
|
|||
}
|
||||
|
||||
buf_handle = req->bo_req.handle;
|
||||
buf_reloc_handle = arg.reloc_handle;
|
||||
reloc_user_ptr = (uint32_t *)(unsigned long)arg.reloc_ptr;
|
||||
|
||||
if (buf_reloc_handle) {
|
||||
ret = i915_exec_reloc(file_priv, buf_handle, buf_reloc_handle, buffers, buf_count);
|
||||
if (reloc_user_ptr) {
|
||||
ret = i915_exec_reloc(file_priv, buf_handle, reloc_user_ptr, buffers, buf_count);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
DRM_MEMORYBARRIER();
|
||||
}
|
||||
|
||||
rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
|
||||
req->bo_req.fence_class,
|
||||
req->bo_req.flags,
|
||||
req->bo_req.mask,
|
||||
req->bo_req.flags, req->bo_req.mask,
|
||||
req->bo_req.hint,
|
||||
0,
|
||||
req->bo_req.fence_class, 0,
|
||||
&rep.bo_info,
|
||||
&buffers[buf_count].buffer);
|
||||
|
||||
|
|
@ -1092,7 +1081,8 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
|
|||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
/* fence */
|
||||
ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence);
|
||||
ret = drm_fence_buffer_objects(dev, NULL, fence_arg->flags,
|
||||
NULL, &fence);
|
||||
if (ret)
|
||||
goto out_err0;
|
||||
|
||||
|
|
@ -1174,7 +1164,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
|||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1208,7 +1198,7 @@ static int i915_setparam(struct drm_device *dev, void *data,
|
|||
drm_i915_setparam_t *param = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1252,7 +1242,7 @@ static int i915_mmio(struct drm_device *dev, void *data,
|
|||
int i;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1295,7 +1285,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
|||
drm_i915_hws_addr_t *hws = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
|
||||
|
|
|
|||
|
|
@ -329,9 +329,9 @@ typedef struct drm_i915_hws_addr {
|
|||
|
||||
/*
|
||||
* Relocation header is 4 uint32_ts
|
||||
* 0 - (16-bit relocation type << 16)| 16 bit reloc count
|
||||
* 1 - buffer handle for another list of relocs
|
||||
* 2-3 - spare.
|
||||
* 0 - 32 bit reloc count
|
||||
* 1 - 32-bit relocation type
|
||||
* 2-3 - 64-bit user buffer handle ptr for another list of relocs.
|
||||
*/
|
||||
#define I915_RELOC_HEADER 4
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ typedef struct drm_i915_hws_addr {
|
|||
* type 0 relocation has 4-uint32_t stride
|
||||
* 0 - offset into buffer
|
||||
* 1 - delta to add in
|
||||
* 2 - index into buffer list
|
||||
* 2 - buffer handle
|
||||
* 3 - reserved (for optimisations later).
|
||||
*/
|
||||
#define I915_RELOC_TYPE_0 0
|
||||
|
|
@ -347,7 +347,7 @@ typedef struct drm_i915_hws_addr {
|
|||
|
||||
struct drm_i915_op_arg {
|
||||
uint64_t next;
|
||||
uint32_t reloc_handle;
|
||||
uint64_t reloc_ptr;
|
||||
int handled;
|
||||
union {
|
||||
struct drm_bo_op_req req;
|
||||
|
|
|
|||
|
|
@ -271,23 +271,23 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
|
|||
extern int i915_irq_wait(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
extern void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe);
|
||||
extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
|
||||
extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
|
||||
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i915_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void i915_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern int i915_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void i915_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_emit_irq(struct drm_device * dev);
|
||||
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_enable_interrupt (struct drm_device *dev);
|
||||
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
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);
|
||||
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(struct drm_device *dev, void *data,
|
||||
|
|
@ -318,12 +318,12 @@ extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t f
|
|||
#ifdef I915_HAVE_BUFFER
|
||||
/* i915_buffer.c */
|
||||
extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev);
|
||||
extern int i915_fence_types(struct drm_buffer_object *bo, uint32_t *fclass,
|
||||
uint32_t *type);
|
||||
extern int i915_fence_type(struct drm_buffer_object *bo, uint32_t *fclass,
|
||||
uint32_t *type);
|
||||
extern int i915_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
|
||||
extern int i915_init_mem_type(struct drm_device *dev, uint32_t type,
|
||||
struct drm_mem_type_manager *man);
|
||||
extern uint32_t i915_evict_mask(struct drm_buffer_object *bo);
|
||||
extern uint64_t i915_evict_flags(struct drm_buffer_object *bo);
|
||||
extern int i915_move(struct drm_buffer_object *bo, int evict,
|
||||
int no_wait, struct drm_bo_mem_reg *new_mem);
|
||||
void i915_flush_ttm(struct drm_ttm *ttm);
|
||||
|
|
@ -354,8 +354,8 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
|
|||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I915_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
|
||||
(n), __FUNCTION__); \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d)\n", \
|
||||
(n)); \
|
||||
if (dev_priv->ring.space < (n)*4) \
|
||||
i915_wait_ring(dev, (n)*4, __FUNCTION__); \
|
||||
outcount = 0; \
|
||||
|
|
@ -516,8 +516,41 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define I915REG_INT_ENABLE_R 0x020a0
|
||||
#define I915REG_INSTPM 0x020c0
|
||||
|
||||
#define PIPEADSL 0x70000
|
||||
#define PIPEBDSL 0x71000
|
||||
|
||||
#define I915REG_PIPEASTAT 0x70024
|
||||
#define I915REG_PIPEBSTAT 0x71024
|
||||
/*
|
||||
* The two pipe frame counter registers are not synchronized, so
|
||||
* reading a stable value is somewhat tricky. The following code
|
||||
* should work:
|
||||
*
|
||||
* do {
|
||||
* high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
|
||||
* PIPE_FRAME_HIGH_SHIFT;
|
||||
* low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
|
||||
* PIPE_FRAME_LOW_SHIFT);
|
||||
* high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
|
||||
* PIPE_FRAME_HIGH_SHIFT);
|
||||
* } while (high1 != high2);
|
||||
* frame = (high1 << 8) | low1;
|
||||
*/
|
||||
#define PIPEAFRAMEHIGH 0x70040
|
||||
#define PIPEBFRAMEHIGH 0x71040
|
||||
#define PIPE_FRAME_HIGH_MASK 0x0000ffff
|
||||
#define PIPE_FRAME_HIGH_SHIFT 0
|
||||
#define PIPEAFRAMEPIXEL 0x70044
|
||||
#define PIPEBFRAMEPIXEL 0x71044
|
||||
|
||||
#define PIPE_FRAME_LOW_MASK 0xff000000
|
||||
#define PIPE_FRAME_LOW_SHIFT 24
|
||||
/*
|
||||
* Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
|
||||
* and is 24 bits wide.
|
||||
*/
|
||||
#define PIPE_PIXEL_MASK 0x00ffffff
|
||||
#define PIPE_PIXEL_SHIFT 0
|
||||
|
||||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_VBLANK_CLEAR (1UL<<1)
|
||||
|
|
@ -871,6 +904,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define BCLRPAT_B 0x61020
|
||||
#define VSYNCSHIFT_B 0x61028
|
||||
|
||||
#define HACTIVE_MASK 0x00000fff
|
||||
#define VTOTAL_MASK 0x00001fff
|
||||
#define VTOTAL_SHIFT 16
|
||||
#define VACTIVE_MASK 0x00000fff
|
||||
#define VBLANK_END_MASK 0x00001fff
|
||||
#define VBLANK_END_SHIFT 16
|
||||
#define VBLANK_START_MASK 0x00001fff
|
||||
|
||||
#define PP_STATUS 0x61200
|
||||
# define PP_ON (1 << 31)
|
||||
/**
|
||||
|
|
@ -1274,7 +1315,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define IS_I855(dev) ((dev)->pci_device == 0x3582)
|
||||
#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
|
||||
|
||||
#define IS_I915G(dev) (dev->pci_device == 0x2582)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/
|
||||
#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
|
||||
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
|
||||
#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
|
||||
#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2)
|
||||
|
|
@ -1284,10 +1325,13 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
(dev)->pci_device == 0x2992 || \
|
||||
(dev)->pci_device == 0x29A2 || \
|
||||
(dev)->pci_device == 0x2A02 || \
|
||||
(dev)->pci_device == 0x2A12)
|
||||
(dev)->pci_device == 0x2A12 || \
|
||||
(dev)->pci_device == 0x2A42)
|
||||
|
||||
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
|
||||
|
||||
#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
|
||||
|
||||
#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
|
||||
(dev)->pci_device == 0x29B2 || \
|
||||
(dev)->pci_device == 0x29D2)
|
||||
|
|
@ -1296,7 +1340,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
|
||||
|
||||
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
|
||||
IS_I945GM(dev) || IS_I965GM(dev))
|
||||
IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
|
||||
|
||||
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@
|
|||
* @dev: DRM device
|
||||
* @plane: plane to look for
|
||||
*
|
||||
* We need to get the pipe associated with a given plane to correctly perform
|
||||
* vblank driven swapping, and they may not always be equal. So look up the
|
||||
* pipe associated with @plane here.
|
||||
* The Intel Mesa & 2D drivers call the vblank routines with a plane number
|
||||
* rather than a pipe number, since they may not always be equal. This routine
|
||||
* maps the given @plane back to a pipe number.
|
||||
*/
|
||||
static int
|
||||
i915_get_pipe(struct drm_device *dev, int plane)
|
||||
|
|
@ -60,6 +60,44 @@ i915_get_pipe(struct drm_device *dev, int plane)
|
|||
return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_get_plane - return the the plane associated with a given pipe
|
||||
* @dev: DRM device
|
||||
* @pipe: pipe to look for
|
||||
*
|
||||
* The Intel Mesa & 2D drivers call the vblank routines with a plane number
|
||||
* rather than a plane number, since they may not always be equal. This routine
|
||||
* maps the given @pipe back to a plane number.
|
||||
*/
|
||||
static int
|
||||
i915_get_plane(struct drm_device *dev, int pipe)
|
||||
{
|
||||
if (i915_get_pipe(dev, 0) == pipe)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_pipe_enabled - check if a pipe is enabled
|
||||
* @dev: DRM device
|
||||
* @pipe: pipe to check
|
||||
*
|
||||
* Reading certain registers when the pipe is disabled can hang the chip.
|
||||
* Use this routine to make sure the PLL is running and the pipe is active
|
||||
* before reading such registers if unsure.
|
||||
*/
|
||||
static int
|
||||
i915_pipe_enabled(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
|
||||
|
||||
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a synchronous flip.
|
||||
*
|
||||
|
|
@ -117,8 +155,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
struct list_head *list, *tmp, hits, *hit;
|
||||
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
|
||||
unsigned counter[2] = { atomic_read(&dev->vbl_received),
|
||||
atomic_read(&dev->vbl_received2) };
|
||||
unsigned counter[2];
|
||||
struct drm_drawable_info *drw;
|
||||
struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv;
|
||||
u32 cpp = dev_priv->cpp, offsets[3];
|
||||
|
|
@ -130,6 +167,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
|||
(cpp << 23) | (1 << 24);
|
||||
RING_LOCALS;
|
||||
|
||||
counter[0] = drm_vblank_count(dev, 0);
|
||||
counter[1] = drm_vblank_count(dev, 1);
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
INIT_LIST_HEAD(&hits);
|
||||
|
|
@ -154,6 +194,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
|||
|
||||
list_del(list);
|
||||
dev_priv->swaps_pending--;
|
||||
drm_vblank_put(dev, pipe);
|
||||
|
||||
DRM_SPINUNLOCK(&dev_priv->swaps_lock);
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
|
|
@ -303,6 +344,73 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
|||
drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
static int i915_in_vblank(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
unsigned long pipedsl, vblank, vtotal;
|
||||
unsigned long vbl_start, vbl_end, cur_line;
|
||||
|
||||
pipedsl = pipe ? PIPEBDSL : PIPEADSL;
|
||||
vblank = pipe ? VBLANK_B : VBLANK_A;
|
||||
vtotal = pipe ? VTOTAL_B : VTOTAL_A;
|
||||
|
||||
vbl_start = I915_READ(vblank) & VBLANK_START_MASK;
|
||||
vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK;
|
||||
|
||||
cur_line = I915_READ(pipedsl);
|
||||
|
||||
if (cur_line >= vbl_start)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
unsigned long high_frame;
|
||||
unsigned long low_frame;
|
||||
u32 high1, high2, low, count;
|
||||
int pipe;
|
||||
|
||||
pipe = i915_get_pipe(dev, plane);
|
||||
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
|
||||
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||
|
||||
if (!i915_pipe_enabled(dev, pipe)) {
|
||||
printk(KERN_ERR "trying to get vblank count for disabled "
|
||||
"pipe %d\n", pipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* High & low register fields aren't synchronized, so make sure
|
||||
* we get a low value that's stable across two reads of the high
|
||||
* register.
|
||||
*/
|
||||
do {
|
||||
high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
|
||||
PIPE_FRAME_LOW_SHIFT);
|
||||
high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
} while (high1 != high2);
|
||||
|
||||
count = (high1 << 8) | low;
|
||||
|
||||
/*
|
||||
* If we're in the middle of the vblank period, the
|
||||
* above regs won't have been updated yet, so return
|
||||
* an incremented count to stay accurate
|
||||
*/
|
||||
#if 0
|
||||
if (i915_in_vblank(dev, pipe))
|
||||
count++;
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
#define HOTPLUG_CMD_CRT 1
|
||||
#define HOTPLUG_CMD_SDVOB 4
|
||||
|
|
@ -445,11 +553,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
|
||||
|
||||
/* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */
|
||||
if (IS_I9XX(dev)) {
|
||||
if (IS_I9XX(dev))
|
||||
temp = I915_READ(I915REG_INT_IDENTITY_R);
|
||||
} else {
|
||||
else
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
}
|
||||
|
||||
temp2 = temp;
|
||||
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
|
||||
|
|
@ -464,7 +571,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
}
|
||||
#else
|
||||
#if 0
|
||||
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
|
||||
DRM_DEBUG("flag=%08x\n", temp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -479,8 +586,32 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
(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) {
|
||||
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) {
|
||||
drm_handle_vblank(dev, i915_get_plane(dev, 1));
|
||||
I915_WRITE(I915REG_PIPEBSTAT,
|
||||
pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE |
|
||||
I915_VBLANK_CLEAR);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
if (temp & USER_INT_FLAG) {
|
||||
|
|
@ -491,32 +622,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
}
|
||||
|
||||
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
|
||||
int vblank_pipe = dev_priv->vblank_pipe;
|
||||
|
||||
if ((vblank_pipe &
|
||||
(DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
|
||||
== (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
|
||||
if (temp & VSYNC_PIPEA_FLAG)
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (temp & VSYNC_PIPEB_FLAG)
|
||||
atomic_inc(&dev->vbl_received2);
|
||||
} else if (((temp & VSYNC_PIPEA_FLAG) &&
|
||||
(vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
|
||||
((temp & VSYNC_PIPEB_FLAG) &&
|
||||
(vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
|
||||
atomic_inc(&dev->vbl_received);
|
||||
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
|
||||
if (dev_priv->swaps_pending > 0)
|
||||
drm_locked_tasklet(dev, i915_vblank_tasklet);
|
||||
I915_WRITE(I915REG_PIPEASTAT,
|
||||
pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
I915_WRITE(I915REG_PIPEBSTAT,
|
||||
pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
}
|
||||
|
||||
/* for now lest just ack it */
|
||||
|
|
@ -535,13 +642,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
int i915_emit_irq(struct drm_device *dev)
|
||||
{
|
||||
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
i915_emit_breadcrumb(dev);
|
||||
|
||||
|
|
@ -580,7 +686,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
|||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
|
||||
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
|
||||
READ_BREADCRUMB(dev_priv));
|
||||
|
||||
if (READ_BREADCRUMB(dev_priv) >= irq_nr)
|
||||
|
|
@ -592,8 +698,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
|||
i915_user_irq_off(dev_priv);
|
||||
|
||||
if (ret == -EBUSY) {
|
||||
DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
|
||||
__FUNCTION__,
|
||||
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
|
||||
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
|
||||
}
|
||||
|
||||
|
|
@ -601,64 +706,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int i915_driver_vblank_do_wait(struct drm_device *dev,
|
||||
unsigned int *sequence,
|
||||
atomic_t *counter)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(counter))
|
||||
- *sequence) <= (1<<23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe)
|
||||
{
|
||||
unsigned int seq;
|
||||
|
||||
seq = pipe ? atomic_read(&dev->vbl_received2) + 1 :
|
||||
atomic_read(&dev->vbl_received) + 1;
|
||||
|
||||
if (!pipe)
|
||||
i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received);
|
||||
else
|
||||
i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received2);
|
||||
}
|
||||
|
||||
int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
atomic_t *counter;
|
||||
|
||||
if (i915_get_pipe(dev, 0) == 0)
|
||||
counter = &dev->vbl_received;
|
||||
else
|
||||
counter = &dev->vbl_received2;
|
||||
return i915_driver_vblank_do_wait(dev, sequence, counter);
|
||||
}
|
||||
|
||||
int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
atomic_t *counter;
|
||||
|
||||
if (i915_get_pipe(dev, 1) == 0)
|
||||
counter = &dev->vbl_received;
|
||||
else
|
||||
counter = &dev->vbl_received2;
|
||||
|
||||
return i915_driver_vblank_do_wait(dev, sequence, counter);
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
int i915_irq_emit(struct drm_device *dev, void *data,
|
||||
|
|
@ -671,7 +718,7 @@ int i915_irq_emit(struct drm_device *dev, void *data,
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -694,24 +741,63 @@ int i915_irq_wait(struct drm_device *dev, void *data,
|
|||
struct drm_i915_irq_wait *irqwait = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return i915_wait_irq(dev, irqwait->irq_seq);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
|
||||
break;
|
||||
case 1:
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
|
||||
pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
|
||||
break;
|
||||
case 1:
|
||||
dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
|
||||
pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
|
||||
dev_priv->irq_enable_reg |= USER_INT_FLAG;
|
||||
|
||||
if (IS_I9XX(dev) && dev->mode_config.num_output) {
|
||||
dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
|
||||
|
|
@ -760,20 +846,17 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
|
|||
struct drm_i915_vblank_pipe *pipe = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
|
||||
DRM_ERROR("%s called with invalid pipe 0x%x\n",
|
||||
__FUNCTION__, pipe->pipe);
|
||||
DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_priv->vblank_pipe = pipe->pipe;
|
||||
|
||||
i915_enable_interrupt (dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -785,7 +868,7 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
|
|||
u16 flag;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -811,6 +894,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||
unsigned int pipe, seqtype, curseq, plane;
|
||||
unsigned long irqflags;
|
||||
struct list_head *list;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __func__);
|
||||
|
|
@ -854,7 +938,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
|
||||
|
||||
curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
|
||||
drm_update_vblank_count(dev, pipe);
|
||||
curseq = drm_vblank_count(dev, pipe);
|
||||
|
||||
if (seqtype == _DRM_VBLANK_RELATIVE)
|
||||
swap->sequence += curseq;
|
||||
|
|
@ -927,6 +1012,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (ret) {
|
||||
drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vbl_swap->drw_id = swap->drawable;
|
||||
vbl_swap->plane = plane;
|
||||
vbl_swap->sequence = swap->sequence;
|
||||
|
|
@ -937,7 +1028,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||
|
||||
DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head);
|
||||
list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head);
|
||||
dev_priv->swaps_pending++;
|
||||
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags);
|
||||
|
|
@ -962,9 +1053,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|||
|
||||
}
|
||||
|
||||
void i915_driver_irq_postinstall(struct drm_device * dev)
|
||||
int i915_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
int ret, num_pipes = 2;
|
||||
|
||||
DRM_SPININIT(&dev_priv->swaps_lock, "swap");
|
||||
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
|
||||
|
|
@ -972,6 +1064,13 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
|
|||
|
||||
DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
|
||||
dev_priv->user_irq_refcount = 0;
|
||||
dev_priv->irq_enable_reg = 0;
|
||||
|
||||
ret = drm_vblank_init(dev, num_pipes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
|
||||
i915_enable_interrupt(dev);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
|
@ -981,6 +1080,7 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
|
|||
*/
|
||||
|
||||
I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ int i915_mem_alloc(struct drm_device *dev, void *data,
|
|||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +314,7 @@ int i915_mem_free(struct drm_device *dev, void *data,
|
|||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ int i915_mem_init_heap(struct drm_device *dev, void *data,
|
|||
struct mem_block **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -366,7 +366,7 @@ int i915_mem_destroy_heap( struct drm_device *dev, void *data,
|
|||
struct mem_block **heap;
|
||||
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||
DRM_ERROR( "called with no initialization\n" );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
* \returns zero on success, or -EBUSY if the timeout (specificed by
|
||||
* drm_mach64_private::usec_timeout) occurs.
|
||||
*/
|
||||
int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries)
|
||||
int mach64_do_wait_for_fifo(drm_mach64_private_t *dev_priv, int entries)
|
||||
{
|
||||
int slots = 0, i;
|
||||
|
||||
|
|
@ -68,15 +68,14 @@ int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries)
|
|||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
DRM_INFO("%s failed! slots=%d entries=%d\n", __FUNCTION__, slots,
|
||||
entries);
|
||||
DRM_INFO("failed! slots=%d entries=%d\n", slots, entries);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the draw engine to be idle.
|
||||
*/
|
||||
int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_wait_for_idle(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
|
|
@ -85,14 +84,12 @@ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv)
|
|||
return ret;
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) {
|
||||
if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE))
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
|
||||
MACH64_READ(MACH64_GUI_STAT));
|
||||
DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT));
|
||||
mach64_dump_ring_info(dev_priv);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
@ -116,7 +113,7 @@ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv)
|
|||
*
|
||||
* \sa mach64_dump_ring_info()
|
||||
*/
|
||||
int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n)
|
||||
int mach64_wait_ring(drm_mach64_private_t *dev_priv, int n)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
int i;
|
||||
|
|
@ -124,9 +121,8 @@ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n)
|
|||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
mach64_update_ring_snapshot(dev_priv);
|
||||
if (ring->space >= n) {
|
||||
if (i > 0) {
|
||||
DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i);
|
||||
}
|
||||
if (i > 0)
|
||||
DRM_DEBUG("%d usecs\n", i);
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
|
|
@ -143,7 +139,7 @@ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n)
|
|||
*
|
||||
* \sa mach64_wait_ring()
|
||||
*/
|
||||
static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
|
||||
static int mach64_ring_idle(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
u32 head;
|
||||
|
|
@ -155,9 +151,8 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
|
|||
mach64_update_ring_snapshot(dev_priv);
|
||||
if (ring->head == ring->tail &&
|
||||
!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) {
|
||||
if (i > 0) {
|
||||
DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i);
|
||||
}
|
||||
if (i > 0)
|
||||
DRM_DEBUG("%d usecs\n", i);
|
||||
return 0;
|
||||
}
|
||||
if (ring->head == head) {
|
||||
|
|
@ -169,8 +164,7 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
|
|||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
|
||||
MACH64_READ(MACH64_GUI_STAT));
|
||||
DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT));
|
||||
mach64_dump_ring_info(dev_priv);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
@ -180,7 +174,7 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
|
|||
*
|
||||
* \sa mach64_do_engine_reset()
|
||||
*/
|
||||
static void mach64_ring_reset(drm_mach64_private_t * dev_priv)
|
||||
static void mach64_ring_reset(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
|
||||
|
|
@ -198,7 +192,7 @@ static void mach64_ring_reset(drm_mach64_private_t * dev_priv)
|
|||
/**
|
||||
* Ensure the all the queued commands will be processed.
|
||||
*/
|
||||
int mach64_do_dma_flush(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_dma_flush(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
/* FIXME: It's not necessary to wait for idle when flushing
|
||||
* we just need to ensure the ring will be completely processed
|
||||
|
|
@ -210,14 +204,14 @@ int mach64_do_dma_flush(drm_mach64_private_t * dev_priv)
|
|||
/**
|
||||
* Stop all DMA activity.
|
||||
*/
|
||||
int mach64_do_dma_idle(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_dma_idle(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* wait for completion */
|
||||
if ((ret = mach64_ring_idle(dev_priv)) < 0) {
|
||||
DRM_ERROR("%s failed BM_GUI_TABLE=0x%08x tail: %u\n",
|
||||
__FUNCTION__, MACH64_READ(MACH64_BM_GUI_TABLE),
|
||||
DRM_ERROR("failed BM_GUI_TABLE=0x%08x tail: %u\n",
|
||||
MACH64_READ(MACH64_BM_GUI_TABLE),
|
||||
dev_priv->ring.tail);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -232,11 +226,11 @@ int mach64_do_dma_idle(drm_mach64_private_t * dev_priv)
|
|||
/**
|
||||
* Reset the engine. This will stop the DMA if it is running.
|
||||
*/
|
||||
int mach64_do_engine_reset(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_engine_reset(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* Kill off any outstanding DMA transfers.
|
||||
*/
|
||||
|
|
@ -276,7 +270,7 @@ int mach64_do_engine_reset(drm_mach64_private_t * dev_priv)
|
|||
/**
|
||||
* Dump engine registers values.
|
||||
*/
|
||||
void mach64_dump_engine_info(drm_mach64_private_t * dev_priv)
|
||||
void mach64_dump_engine_info(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
DRM_INFO("\n");
|
||||
if (!dev_priv->is_pci) {
|
||||
|
|
@ -417,8 +411,8 @@ void mach64_dump_engine_info(drm_mach64_private_t * dev_priv)
|
|||
* Used by mach64_dump_ring_info() to dump the contents of the current buffer
|
||||
* pointed by the ring head.
|
||||
*/
|
||||
static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv,
|
||||
struct drm_buf * buf)
|
||||
static void mach64_dump_buf_info(drm_mach64_private_t *dev_priv,
|
||||
struct drm_buf *buf)
|
||||
{
|
||||
u32 addr = GETBUFADDR(buf);
|
||||
u32 used = buf->used >> 2;
|
||||
|
|
@ -477,7 +471,7 @@ static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv,
|
|||
* Dump the ring state and contents, including the contents of the buffer being
|
||||
* processed by the graphics engine.
|
||||
*/
|
||||
void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
|
||||
void mach64_dump_ring_info(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
int i, skipped;
|
||||
|
|
@ -526,9 +520,8 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
|
|||
|
||||
u32 buf_addr = GETBUFADDR(buf);
|
||||
|
||||
if (buf_addr <= addr && addr < buf_addr + buf->used) {
|
||||
if (buf_addr <= addr && addr < buf_addr + buf->used)
|
||||
mach64_dump_buf_info(dev_priv, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -564,13 +557,13 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
|
|||
|
||||
/**
|
||||
* Add the end mark to the ring's new tail position.
|
||||
*
|
||||
*
|
||||
* The bus master engine will keep processing the DMA buffers listed in the ring
|
||||
* until it finds this mark, making it stop.
|
||||
*
|
||||
*
|
||||
* \sa mach64_clear_dma_eol
|
||||
*/
|
||||
static __inline__ void mach64_set_dma_eol(volatile u32 * addr)
|
||||
static __inline__ void mach64_set_dma_eol(volatile u32 *addr)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
int nr = 31;
|
||||
|
|
@ -611,17 +604,17 @@ static __inline__ void mach64_set_dma_eol(volatile u32 * addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove the end mark from the ring's old tail position.
|
||||
*
|
||||
* Remove the end mark from the ring's old tail position.
|
||||
*
|
||||
* It should be called after calling mach64_set_dma_eol to mark the ring's new
|
||||
* tail position.
|
||||
*
|
||||
* We update the end marks while the bus master engine is in operation. Since
|
||||
*
|
||||
* We update the end marks while the bus master engine is in operation. Since
|
||||
* the bus master engine may potentially be reading from the same position
|
||||
* that we write, we must change atomically to avoid having intermediary bad
|
||||
* that we write, we must change atomically to avoid having intermediary bad
|
||||
* data.
|
||||
*/
|
||||
static __inline__ void mach64_clear_dma_eol(volatile u32 * addr)
|
||||
static __inline__ void mach64_clear_dma_eol(volatile u32 *addr)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
int nr = 31;
|
||||
|
|
@ -661,35 +654,35 @@ static __inline__ void mach64_clear_dma_eol(volatile u32 * addr)
|
|||
#endif
|
||||
}
|
||||
|
||||
#define RING_LOCALS \
|
||||
#define RING_LOCALS \
|
||||
int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring
|
||||
|
||||
#define RING_WRITE_OFS _ring_write
|
||||
|
||||
#define BEGIN_RING( n ) \
|
||||
do { \
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
||||
(n), __FUNCTION__ ); \
|
||||
} \
|
||||
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
|
||||
int ret; \
|
||||
if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \
|
||||
DRM_ERROR( "wait_ring failed, resetting engine\n"); \
|
||||
mach64_dump_engine_info( dev_priv ); \
|
||||
mach64_do_engine_reset( dev_priv ); \
|
||||
return ret; \
|
||||
} \
|
||||
} \
|
||||
dev_priv->ring.space -= (n) * sizeof(u32); \
|
||||
_ring = (u32 *) dev_priv->ring.start; \
|
||||
_ring_tail = _ring_write = dev_priv->ring.tail; \
|
||||
_ring_mask = dev_priv->ring.tail_mask; \
|
||||
} while (0)
|
||||
#define BEGIN_RING(n) \
|
||||
do { \
|
||||
if (MACH64_VERBOSE) { \
|
||||
DRM_INFO( "BEGIN_RING( %d ) \n", \
|
||||
(n) ); \
|
||||
} \
|
||||
if (dev_priv->ring.space <= (n) * sizeof(u32)) { \
|
||||
int ret; \
|
||||
if ((ret = mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \
|
||||
DRM_ERROR( "wait_ring failed, resetting engine\n"); \
|
||||
mach64_dump_engine_info( dev_priv ); \
|
||||
mach64_do_engine_reset( dev_priv ); \
|
||||
return ret; \
|
||||
} \
|
||||
} \
|
||||
dev_priv->ring.space -= (n) * sizeof(u32); \
|
||||
_ring = (u32 *) dev_priv->ring.start; \
|
||||
_ring_tail = _ring_write = dev_priv->ring.tail; \
|
||||
_ring_mask = dev_priv->ring.tail_mask; \
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING( x ) \
|
||||
do { \
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
if (MACH64_VERBOSE) { \
|
||||
DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
|
||||
(unsigned int)(x), _ring_write ); \
|
||||
} \
|
||||
|
|
@ -699,7 +692,7 @@ do { \
|
|||
|
||||
#define ADVANCE_RING() \
|
||||
do { \
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
if (MACH64_VERBOSE) { \
|
||||
DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
|
||||
_ring_write, _ring_tail ); \
|
||||
} \
|
||||
|
|
@ -835,7 +828,7 @@ static int mach64_bm_dma_test(struct drm_device * dev)
|
|||
u32 src_cntl, pat_reg0, pat_reg1;
|
||||
int i, count, failed;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
table = (u32 *) dev_priv->ring.start;
|
||||
|
||||
|
|
@ -1011,7 +1004,7 @@ static int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init)
|
|||
u32 tmp;
|
||||
int i, ret;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
|
|
@ -1221,7 +1214,7 @@ static int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init)
|
|||
/** MMIO Pseudo-DMA (intended primarily for debugging, not performance)
|
||||
*/
|
||||
|
||||
int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
volatile u32 *ring_read;
|
||||
|
|
@ -1236,9 +1229,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
|
|||
target = MACH64_BM_ADDR;
|
||||
|
||||
if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) {
|
||||
DRM_INFO
|
||||
("%s: idle failed before pseudo-dma dispatch, resetting engine\n",
|
||||
__FUNCTION__);
|
||||
DRM_INFO("idle failed before pseudo-dma dispatch, resetting engine\n");
|
||||
mach64_dump_engine_info(dev_priv);
|
||||
mach64_do_engine_reset(dev_priv);
|
||||
return ret;
|
||||
|
|
@ -1359,7 +1350,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
|
|||
MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
|
||||
ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
|
||||
|
||||
DRM_DEBUG("%s completed\n", __FUNCTION__);
|
||||
DRM_DEBUG("completed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1372,7 +1363,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
|
|||
|
||||
int mach64_do_cleanup_dma(struct drm_device * dev)
|
||||
{
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* Make sure interrupts are disabled here because the uninstall ioctl
|
||||
* may not have been called from userspace and after dev_private
|
||||
|
|
@ -1416,7 +1407,7 @@ int mach64_dma_init(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_mach64_init_t *init = data;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1435,7 +1426,7 @@ int mach64_dma_idle(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1447,7 +1438,7 @@ int mach64_dma_flush(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1459,7 +1450,7 @@ int mach64_engine_reset(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1481,8 +1472,7 @@ int mach64_init_freelist(struct drm_device * dev)
|
|||
struct list_head *ptr;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("%s: adding %d buffers to freelist\n", __FUNCTION__,
|
||||
dma->buf_count);
|
||||
DRM_DEBUG("adding %d buffers to freelist\n", dma->buf_count);
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if ((entry =
|
||||
|
|
@ -1506,7 +1496,7 @@ void mach64_destroy_freelist(struct drm_device * dev)
|
|||
struct list_head *ptr;
|
||||
struct list_head *tmp;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
list_for_each_safe(ptr, tmp, &dev_priv->pending) {
|
||||
list_del(ptr);
|
||||
|
|
@ -1529,7 +1519,7 @@ void mach64_destroy_freelist(struct drm_device * dev)
|
|||
/* IMPORTANT: This function should only be called when the engine is idle or locked up,
|
||||
* as it assumes all buffers in the pending list have been completed by the hardware.
|
||||
*/
|
||||
int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv)
|
||||
int mach64_do_release_used_buffers(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
struct list_head *ptr;
|
||||
struct list_head *tmp;
|
||||
|
|
@ -1551,13 +1541,12 @@ int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv)
|
|||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG("%s: released %d buffers from pending list\n", __FUNCTION__,
|
||||
i);
|
||||
DRM_DEBUG("released %d buffers from pending list\n", i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
|
||||
static int mach64_do_reclaim_completed(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
struct list_head *ptr;
|
||||
|
|
@ -1579,8 +1568,7 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
|
|||
#endif
|
||||
/* last pass is complete, so release everything */
|
||||
mach64_do_release_used_buffers(dev_priv);
|
||||
DRM_DEBUG("%s: idle engine, freed all buffers.\n",
|
||||
__FUNCTION__);
|
||||
DRM_DEBUG("idle engine, freed all buffers.\n");
|
||||
if (list_empty(&dev_priv->free_list)) {
|
||||
DRM_ERROR("Freelist empty with idle engine\n");
|
||||
return -1;
|
||||
|
|
@ -1621,9 +1609,9 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
|
|||
list_del(ptr);
|
||||
list_add_tail(ptr, &dev_priv->free_list);
|
||||
DRM_DEBUG
|
||||
("%s: freed processed buffer (head=%d tail=%d "
|
||||
("freed processed buffer (head=%d tail=%d "
|
||||
"buf ring ofs=%d).\n",
|
||||
__FUNCTION__, head, tail, ofs);
|
||||
head, tail, ofs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1631,7 +1619,7 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv)
|
||||
struct drm_buf *mach64_freelist_get(drm_mach64_private_t *dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
drm_mach64_freelist_t *entry;
|
||||
|
|
@ -1677,7 +1665,7 @@ struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv)
|
|||
return entry->buf;
|
||||
}
|
||||
|
||||
int mach64_freelist_put(drm_mach64_private_t * dev_priv, struct drm_buf * copy_buf)
|
||||
int mach64_freelist_put(drm_mach64_private_t *dev_priv, struct drm_buf *copy_buf)
|
||||
{
|
||||
struct list_head *ptr;
|
||||
drm_mach64_freelist_t *entry;
|
||||
|
|
@ -1686,8 +1674,7 @@ int mach64_freelist_put(drm_mach64_private_t * dev_priv, struct drm_buf * copy_b
|
|||
list_for_each(ptr, &dev_priv->pending) {
|
||||
entry = list_entry(ptr, drm_mach64_freelist_t, list);
|
||||
if (copy_buf == entry->buf) {
|
||||
DRM_ERROR("%s: Trying to release a pending buf\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("Trying to release a pending buf\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ typedef struct drm_mach64_private {
|
|||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
atomic_t vbl_received; /**< Number of vblanks received. */
|
||||
|
||||
u32 front_offset_pitch;
|
||||
u32 back_offset_pitch;
|
||||
u32 depth_offset_pitch;
|
||||
|
|
@ -160,13 +162,14 @@ extern int mach64_dma_blit(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv);
|
||||
extern int mach64_get_param(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int mach64_driver_vblank_wait(struct drm_device * dev,
|
||||
unsigned int *sequence);
|
||||
|
||||
extern u32 mach64_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int mach64_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void mach64_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void mach64_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void mach64_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void mach64_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern void mach64_driver_irq_preinstall(struct drm_device *dev);
|
||||
extern int mach64_driver_irq_postinstall(struct drm_device *dev);
|
||||
extern void mach64_driver_irq_uninstall(struct drm_device *dev);
|
||||
|
||||
/* ================================================================
|
||||
* Registers
|
||||
|
|
@ -536,8 +539,7 @@ static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv)
|
|||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
|
||||
DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
ring->head_addr, ring->head, ring->tail, ring->space);
|
||||
|
||||
if (mach64_do_wait_for_idle(dev_priv) < 0) {
|
||||
|
|
@ -563,8 +565,7 @@ static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv)
|
|||
static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
|
||||
drm_mach64_descriptor_ring_t * ring)
|
||||
{
|
||||
DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
ring->head_addr, ring->head, ring->tail, ring->space);
|
||||
|
||||
/* reset descriptor table ring head */
|
||||
|
|
@ -583,8 +584,7 @@ static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
|
|||
MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0);
|
||||
if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) {
|
||||
if ((mach64_do_wait_for_idle(dev_priv)) < 0) {
|
||||
DRM_ERROR("%s: idle failed, resetting engine\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("idle failed, resetting engine\n");
|
||||
mach64_dump_engine_info(dev_priv);
|
||||
mach64_do_engine_reset(dev_priv);
|
||||
return;
|
||||
|
|
@ -609,8 +609,7 @@ static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
|
|||
static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv,
|
||||
drm_mach64_descriptor_ring_t * ring)
|
||||
{
|
||||
DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
ring->head_addr, ring->head, ring->tail, ring->space);
|
||||
|
||||
if (!dev_priv->ring_running) {
|
||||
|
|
@ -657,8 +656,7 @@ static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv,
|
|||
|
||||
static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv)
|
||||
{
|
||||
DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n",
|
||||
dev_priv->ring.head_addr, dev_priv->ring.head,
|
||||
dev_priv->ring.tail, dev_priv->ring.space);
|
||||
|
||||
|
|
@ -679,7 +677,7 @@ mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv)
|
|||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
mach64_ring_tick(dev_priv, ring);
|
||||
|
||||
|
|
@ -720,7 +718,7 @@ static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t *
|
|||
struct list_head *ptr;
|
||||
#if MACH64_EXTRA_CHECKING
|
||||
if (list_empty(&dev_priv->pending)) {
|
||||
DRM_ERROR("Empty pending list in %s\n", __FUNCTION__);
|
||||
DRM_ERROR("Empty pending list in \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -747,18 +745,15 @@ do { \
|
|||
#define DMAGETPTR( file_priv, dev_priv, n ) \
|
||||
do { \
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "DMAGETPTR( %d ) in %s\n", \
|
||||
n, __FUNCTION__ ); \
|
||||
DRM_INFO( "DMAGETPTR( %d )\n", (n) ); \
|
||||
} \
|
||||
_buf = mach64_freelist_get( dev_priv ); \
|
||||
if (_buf == NULL) { \
|
||||
DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", \
|
||||
__FUNCTION__ ); \
|
||||
DRM_ERROR("couldn't get buffer in DMAGETPTR\n"); \
|
||||
return -EAGAIN; \
|
||||
} \
|
||||
if (_buf->pending) { \
|
||||
DRM_ERROR("%s: pending buf in DMAGETPTR\n", \
|
||||
__FUNCTION__ ); \
|
||||
DRM_ERROR("pending buf in DMAGETPTR\n"); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
_buf->file_priv = file_priv; \
|
||||
|
|
@ -778,92 +773,87 @@ do { \
|
|||
_buf->used += 8; \
|
||||
} while (0)
|
||||
|
||||
#define DMAADVANCE( dev_priv, _discard ) \
|
||||
do { \
|
||||
struct list_head *ptr; \
|
||||
int ret; \
|
||||
\
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \
|
||||
} \
|
||||
\
|
||||
if (_buf->used <= 0) { \
|
||||
DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n", \
|
||||
__FUNCTION__, _buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
if (_buf->pending) { \
|
||||
/* This is a resued buffer, so we need to find it in the pending list */ \
|
||||
if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \
|
||||
DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \
|
||||
__FUNCTION__, _buf->idx ); \
|
||||
return ret; \
|
||||
} \
|
||||
if (_entry->discard) { \
|
||||
DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \
|
||||
__FUNCTION__, _buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
} else { \
|
||||
if (list_empty(&dev_priv->placeholders)) { \
|
||||
DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n", \
|
||||
__FUNCTION__ ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
ptr = dev_priv->placeholders.next; \
|
||||
list_del(ptr); \
|
||||
_entry = list_entry(ptr, drm_mach64_freelist_t, list); \
|
||||
_buf->pending = 1; \
|
||||
_entry->buf = _buf; \
|
||||
list_add_tail(ptr, &dev_priv->pending); \
|
||||
} \
|
||||
_entry->discard = (_discard); \
|
||||
if ( (ret = mach64_add_buf_to_ring( dev_priv, _entry )) ) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
#define DMAADVANCE( dev_priv, _discard ) \
|
||||
do { \
|
||||
struct list_head *ptr; \
|
||||
int ret; \
|
||||
\
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "DMAADVANCE() in \n" ); \
|
||||
} \
|
||||
\
|
||||
if (_buf->used <= 0) { \
|
||||
DRM_ERROR( "DMAADVANCE(): sending empty buf %d\n", \
|
||||
_buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
if (_buf->pending) { \
|
||||
/* This is a resued buffer, so we need to find it in the pending list */ \
|
||||
if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \
|
||||
DRM_ERROR( "DMAADVANCE(): couldn't find pending buf %d\n", _buf->idx ); \
|
||||
return ret; \
|
||||
} \
|
||||
if (_entry->discard) { \
|
||||
DRM_ERROR( "DMAADVANCE(): sending discarded pending buf %d\n", _buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
} else { \
|
||||
if (list_empty(&dev_priv->placeholders)) { \
|
||||
DRM_ERROR( "DMAADVANCE(): empty placeholder list\n"); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
ptr = dev_priv->placeholders.next; \
|
||||
list_del(ptr); \
|
||||
_entry = list_entry(ptr, drm_mach64_freelist_t, list); \
|
||||
_buf->pending = 1; \
|
||||
_entry->buf = _buf; \
|
||||
list_add_tail(ptr, &dev_priv->pending); \
|
||||
} \
|
||||
_entry->discard = (_discard); \
|
||||
if ((ret = mach64_add_buf_to_ring( dev_priv, _entry ))) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define DMADISCARDBUF() \
|
||||
do { \
|
||||
if (_entry == NULL) { \
|
||||
int ret; \
|
||||
if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \
|
||||
DRM_ERROR( "%s: couldn't find pending buf %d\n", \
|
||||
__FUNCTION__, _buf->idx ); \
|
||||
return ret; \
|
||||
} \
|
||||
} \
|
||||
_entry->discard = 1; \
|
||||
} while(0)
|
||||
#define DMADISCARDBUF() \
|
||||
do { \
|
||||
if (_entry == NULL) { \
|
||||
int ret; \
|
||||
if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \
|
||||
DRM_ERROR( "couldn't find pending buf %d\n", \
|
||||
_buf->idx ); \
|
||||
return ret; \
|
||||
} \
|
||||
} \
|
||||
_entry->discard = 1; \
|
||||
} while(0)
|
||||
|
||||
#define DMAADVANCEHOSTDATA( dev_priv ) \
|
||||
do { \
|
||||
struct list_head *ptr; \
|
||||
int ret; \
|
||||
\
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \
|
||||
} \
|
||||
\
|
||||
if (_buf->used <= 0) { \
|
||||
DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n", \
|
||||
__FUNCTION__, _buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
if (list_empty(&dev_priv->placeholders)) { \
|
||||
DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n", \
|
||||
__FUNCTION__ ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
\
|
||||
ptr = dev_priv->placeholders.next; \
|
||||
list_del(ptr); \
|
||||
_entry = list_entry(ptr, drm_mach64_freelist_t, list); \
|
||||
_entry->buf = _buf; \
|
||||
_entry->buf->pending = 1; \
|
||||
list_add_tail(ptr, &dev_priv->pending); \
|
||||
_entry->discard = 1; \
|
||||
if ( (ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry )) ) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
#define DMAADVANCEHOSTDATA( dev_priv ) \
|
||||
do { \
|
||||
struct list_head *ptr; \
|
||||
int ret; \
|
||||
\
|
||||
if ( MACH64_VERBOSE ) { \
|
||||
DRM_INFO( "DMAADVANCEHOSTDATA() in \n" ); \
|
||||
} \
|
||||
\
|
||||
if (_buf->used <= 0) { \
|
||||
DRM_ERROR( "DMAADVANCEHOSTDATA(): sending empty buf %d\n", _buf->idx ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
if (list_empty(&dev_priv->placeholders)) { \
|
||||
DRM_ERROR( "empty placeholder list in DMAADVANCEHOSTDATA()\n" ); \
|
||||
return -EFAULT; \
|
||||
} \
|
||||
\
|
||||
ptr = dev_priv->placeholders.next; \
|
||||
list_del(ptr); \
|
||||
_entry = list_entry(ptr, drm_mach64_freelist_t, list); \
|
||||
_entry->buf = _buf; \
|
||||
_entry->buf->pending = 1; \
|
||||
list_add_tail(ptr, &dev_priv->pending); \
|
||||
_entry->discard = 1; \
|
||||
if ((ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry ))) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#endif /* __MACH64_DRV_H__ */
|
||||
|
|
|
|||
|
|
@ -42,9 +42,8 @@
|
|||
|
||||
irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
struct drm_device *dev = arg;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
int status;
|
||||
|
||||
status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
|
@ -62,74 +61,81 @@ irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
(status & ~MACH64_CRTC_INT_ACKS)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
drm_handle_vblank(dev, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int mach64_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
u32 mach64_get_vblank_counter(struct drm_device * dev, int crtc)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
const drm_mach64_private_t *const dev_priv = dev->dev_private;
|
||||
|
||||
if (crtc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void mach64_driver_irq_preinstall(struct drm_device * dev)
|
||||
int mach64_enable_vblank(struct drm_device * dev, int crtc)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", crtc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_DEBUG("before enable vblank CRTC_INT_CTNL: 0x%08x\n", status);
|
||||
|
||||
/* Turn on VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
|
||||
| MACH64_CRTC_VBLANK_INT_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void mach64_disable_vblank(struct drm_device * dev, int crtc)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
||||
DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
|
||||
DRM_DEBUG("before disable vblank CRTC_INT_CTNL: 0x%08x\n", status);
|
||||
|
||||
/* Disable and clear VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
}
|
||||
|
||||
void mach64_driver_irq_postinstall(struct drm_device * dev)
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void mach64_driver_irq_preinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
/* Turn on VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
|
||||
| MACH64_CRTC_VBLANK_INT_EN);
|
||||
u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
||||
DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n",
|
||||
MACH64_READ(MACH64_CRTC_INT_CNTL));
|
||||
DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
|
||||
|
||||
mach64_disable_vblank(dev,0);
|
||||
}
|
||||
|
||||
int mach64_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
return drm_vblank_init(dev, 1);
|
||||
}
|
||||
|
||||
void mach64_driver_irq_uninstall(struct drm_device * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
/* Disable and clear VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL,
|
||||
(MACH64_READ(MACH64_CRTC_INT_CNTL) &
|
||||
~MACH64_CRTC_VBLANK_INT_EN)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
mach64_disable_vblank(dev, 0);
|
||||
|
||||
DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n",
|
||||
MACH64_READ(MACH64_CRTC_INT_CNTL));
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static int mach64_emit_cliprect(struct drm_file *file_priv,
|
|||
drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box);
|
||||
DRM_DEBUG("box=%p\n", box);
|
||||
|
||||
/* Get GL scissor */
|
||||
/* FIXME: store scissor in SAREA as a cliprect instead of in
|
||||
|
|
@ -146,7 +146,7 @@ static __inline__ int mach64_emit_state(struct drm_file *file_priv,
|
|||
if (MACH64_VERBOSE) {
|
||||
mach64_print_dirty(__FUNCTION__, dirty);
|
||||
} else {
|
||||
DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
|
||||
DRM_DEBUG("dirty=0x%08x\n", dirty);
|
||||
}
|
||||
|
||||
DMAGETPTR(file_priv, dev_priv, 17); /* returns on failure to get buffer */
|
||||
|
|
@ -229,7 +229,7 @@ static int mach64_dma_dispatch_clear(struct drm_device * dev,
|
|||
int i;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
switch (dev_priv->fb_bpp) {
|
||||
case 16:
|
||||
|
|
@ -368,7 +368,7 @@ static int mach64_dma_dispatch_swap(struct drm_device * dev,
|
|||
int i;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
switch (dev_priv->fb_bpp) {
|
||||
case 16:
|
||||
|
|
@ -445,7 +445,7 @@ static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv)
|
|||
int i, start;
|
||||
u32 head, tail, ofs;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (sarea_priv->frames_queued == 0)
|
||||
return 0;
|
||||
|
|
@ -525,15 +525,14 @@ static __inline__ int copy_from_user_vertex(u32 *to,
|
|||
from += count;
|
||||
to += count;
|
||||
} else {
|
||||
DRM_ERROR("%s: Got bad command: 0x%04x\n",
|
||||
__FUNCTION__, reg);
|
||||
DRM_ERROR("Got bad command: 0x%04x\n", reg);
|
||||
drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
return -EACCES;
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR
|
||||
("%s: Got bad command count(=%u) dwords remaining=%lu\n",
|
||||
__FUNCTION__, count, n);
|
||||
("Got bad command count(=%u) dwords remaining=%lu\n",
|
||||
count, n);
|
||||
drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -543,7 +542,7 @@ static __inline__ int copy_from_user_vertex(u32 *to,
|
|||
if (n == 0)
|
||||
return 0;
|
||||
else {
|
||||
DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes);
|
||||
DRM_ERROR("Bad buf->used(=%lu)\n", bytes);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
@ -563,15 +562,15 @@ static int mach64_dma_dispatch_vertex(struct drm_device * dev,
|
|||
int verify_ret = 0;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n",
|
||||
__FUNCTION__, buf, used, sarea_priv->nbox);
|
||||
DRM_DEBUG("buf=%p used=%lu nbox=%d\n",
|
||||
buf, used, sarea_priv->nbox);
|
||||
|
||||
if (!used)
|
||||
goto _vertex_done;
|
||||
|
||||
copy_buf = mach64_freelist_get(dev_priv);
|
||||
if (copy_buf == NULL) {
|
||||
DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
|
||||
DRM_ERROR("couldn't get buffer\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
@ -698,7 +697,7 @@ static int mach64_dma_dispatch_blit(struct drm_device * dev,
|
|||
|
||||
copy_buf = mach64_freelist_get(dev_priv);
|
||||
if (copy_buf == NULL) {
|
||||
DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
|
||||
DRM_ERROR("couldn't get buffer\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
@ -759,7 +758,7 @@ static int mach64_dma_dispatch_blit(struct drm_device * dev,
|
|||
DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width);
|
||||
|
||||
DRM_DEBUG("%s: %lu bytes\n", __FUNCTION__, used);
|
||||
DRM_DEBUG("%lu bytes\n", used);
|
||||
|
||||
/* Add the buffer to the queue */
|
||||
DMAADVANCEHOSTDATA(dev_priv);
|
||||
|
|
@ -780,7 +779,7 @@ int mach64_dma_clear(struct drm_device *dev, void *data,
|
|||
drm_mach64_clear_t *clear = data;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
|
||||
DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -805,7 +804,7 @@ int mach64_dma_swap(struct drm_device *dev, void *data,
|
|||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
|
||||
DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -830,12 +829,12 @@ int mach64_dma_vertex(struct drm_device *dev, void *data,
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n",
|
||||
__FUNCTION__, DRM_CURRENTPID,
|
||||
DRM_DEBUG("pid=%d buf=%p used=%lu discard=%d\n",
|
||||
DRM_CURRENTPID,
|
||||
vertex->buf, vertex->used, vertex->discard);
|
||||
|
||||
if (vertex->prim < 0 || vertex->prim > MACH64_PRIM_POLYGON) {
|
||||
|
|
@ -882,10 +881,10 @@ int mach64_get_param(struct drm_device *dev, void *data,
|
|||
drm_mach64_getparam_t *param = data;
|
||||
int value;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -997,7 +997,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int mga_dma_init(struct drm_device *dev, void *data,
|
||||
|
|
@ -1049,7 +1049,7 @@ int mga_dma_flush(struct drm_device *dev, void *data,
|
|||
#if MGA_DMA_DEBUG
|
||||
int ret = mga_do_wait_for_idle(dev_priv);
|
||||
if (ret < 0)
|
||||
DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
|
||||
DRM_INFO("-EBUSY\n");
|
||||
return ret;
|
||||
#else
|
||||
return mga_do_wait_for_idle(dev_priv);
|
||||
|
|
|
|||
|
|
@ -113,13 +113,14 @@ typedef struct drm_mga_private {
|
|||
* \sa drm_mga_private_t::mmio
|
||||
*/
|
||||
/*@{*/
|
||||
u32 mmio_base; /**< Bus address of base of MMIO. */
|
||||
u32 mmio_size; /**< Size of the MMIO region. */
|
||||
u32 mmio_base; /**< Bus address of base of MMIO. */
|
||||
u32 mmio_size; /**< Size of the MMIO region. */
|
||||
/*@}*/
|
||||
|
||||
u32 clear_cmd;
|
||||
u32 maccess;
|
||||
|
||||
atomic_t vbl_received; /**< Number of vblanks received. */
|
||||
wait_queue_head_t fence_queue;
|
||||
atomic_t last_fence_retired;
|
||||
u32 next_fence_to_post;
|
||||
|
|
@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
|
|||
extern int mga_warp_init(drm_mga_private_t * dev_priv);
|
||||
|
||||
/* mga_irq.c */
|
||||
extern int mga_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void mga_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void mga_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern int mga_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
|
@ -249,7 +253,7 @@ do { \
|
|||
} else if ( dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
|
||||
DRM_INFO( "wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
} \
|
||||
} \
|
||||
|
|
@ -260,7 +264,7 @@ do { \
|
|||
if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
|
||||
DRM_INFO( "wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
} \
|
||||
mga_do_dma_wrap_end( dev_priv ); \
|
||||
|
|
@ -280,8 +284,7 @@ do { \
|
|||
#define BEGIN_DMA( n ) \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \
|
||||
(n), __FUNCTION__ ); \
|
||||
DRM_INFO( "BEGIN_DMA( %d )\n", (n) ); \
|
||||
DRM_INFO( " space=0x%x req=0x%Zx\n", \
|
||||
dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
|
||||
} \
|
||||
|
|
@ -292,7 +295,7 @@ do { \
|
|||
#define BEGIN_DMA_WRAP() \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \
|
||||
DRM_INFO( "BEGIN_DMA()\n" ); \
|
||||
DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \
|
||||
} \
|
||||
prim = dev_priv->prim.start; \
|
||||
|
|
@ -311,7 +314,7 @@ do { \
|
|||
#define FLUSH_DMA() \
|
||||
do { \
|
||||
if ( 0 ) { \
|
||||
DRM_INFO( "%s:\n", __FUNCTION__ ); \
|
||||
DRM_INFO( "\n" ); \
|
||||
DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
|
||||
dev_priv->prim.tail, \
|
||||
MGA_READ( MGA_PRIMADDRESS ) - \
|
||||
|
|
|
|||
|
|
@ -36,6 +36,20 @@
|
|||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
|
||||
u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
const drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
if (crtc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
|
||||
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
|
|
@ -48,9 +62,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
/* VBLANK interrupt */
|
||||
if (status & MGA_VLINEPEN) {
|
||||
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
drm_handle_vblank(dev, 0);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
|
|
@ -79,22 +92,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
int mga_enable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void mga_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
}
|
||||
|
||||
/* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
|
||||
* a nice hardware counter that tracks the number of refreshes when
|
||||
* the interrupt is disabled, and the kernel doesn't know the refresh
|
||||
* rate to calculate an estimate.
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
|
||||
}
|
||||
|
||||
int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
|
|
@ -126,14 +151,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
|
|||
MGA_WRITE(MGA_ICLEAR, ~0);
|
||||
}
|
||||
|
||||
void mga_driver_irq_postinstall(struct drm_device * dev)
|
||||
int mga_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = drm_vblank_init(dev, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
|
||||
|
||||
/* Turn on vertical blank interrupt and soft trap interrupt. */
|
||||
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
|
||||
/* Turn on soft trap interrupt. Vertical blank interrupts are enabled
|
||||
* in mga_enable_vblank.
|
||||
*/
|
||||
MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mga_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ static void mga_dma_dispatch_swap(struct drm_device * dev)
|
|||
|
||||
FLUSH_DMA();
|
||||
|
||||
DRM_DEBUG("%s... done.\n", __FUNCTION__);
|
||||
DRM_DEBUG("... done.\n");
|
||||
}
|
||||
|
||||
static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
|
||||
|
|
@ -656,7 +656,7 @@ static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * bu
|
|||
u32 length = (u32) buf->used;
|
||||
int i = 0;
|
||||
DMA_LOCALS;
|
||||
DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used);
|
||||
DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
|
||||
|
||||
if (buf->used) {
|
||||
buf_priv->dispatched = 1;
|
||||
|
|
@ -703,7 +703,7 @@ static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * b
|
|||
u32 address = (u32) buf->bus_address;
|
||||
int i = 0;
|
||||
DMA_LOCALS;
|
||||
DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end);
|
||||
DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end);
|
||||
|
||||
if (start != end) {
|
||||
buf_priv->dispatched = 1;
|
||||
|
|
@ -988,7 +988,7 @@ static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
#if 0
|
||||
if (mga_do_wait_for_idle(dev_priv) < 0) {
|
||||
if (MGA_DMA_DEBUG)
|
||||
DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
|
||||
DRM_INFO("-EBUSY\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1047,7 +1047,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil
|
|||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1079,7 +1079,7 @@ static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
DMA_LOCALS;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1108,7 +1108,7 @@ static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *f
|
|||
u32 *fence = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
|
|||
/* nouveau_irq.c */
|
||||
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void nouveau_irq_preinstall(struct drm_device *);
|
||||
extern void nouveau_irq_postinstall(struct drm_device *);
|
||||
extern int nouveau_irq_postinstall(struct drm_device *);
|
||||
extern void nouveau_irq_uninstall(struct drm_device *);
|
||||
|
||||
/* nouveau_sgdma.c */
|
||||
|
|
|
|||
|
|
@ -46,13 +46,15 @@ nouveau_irq_preinstall(struct drm_device *dev)
|
|||
NV_WRITE(NV03_PMC_INTR_EN_0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
nouveau_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* Master enable */
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -619,7 +619,7 @@ alloc_ok:
|
|||
block->map_handle = entry->user_token;
|
||||
}
|
||||
|
||||
DRM_DEBUG("allocated 0x%llx type=0x%08x\n", block->start, block->flags);
|
||||
DRM_DEBUG("allocated %lld bytes at 0x%llx type=0x%08x\n", block->size, block->start, block->flags);
|
||||
return block;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@
|
|||
#define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31)
|
||||
#define NV50_PUNK_UNK1710 0x00001710
|
||||
|
||||
#define NV04_PBUS_PCI_NV_1 0x00001804
|
||||
#define NV04_PBUS_PCI_NV_19 0x0000184C
|
||||
|
||||
#define NV04_PTIMER_INTR_0 0x00009100
|
||||
#define NV04_PTIMER_INTR_EN_0 0x00009140
|
||||
#define NV04_PTIMER_NUMERATOR 0x00009200
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@ static int nouveau_init_card_mappings(struct drm_device *dev)
|
|||
|
||||
static int nouveau_stub_init(struct drm_device *dev) { return 0; }
|
||||
static void nouveau_stub_takedown(struct drm_device *dev) {}
|
||||
static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; }
|
||||
|
||||
static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
{
|
||||
|
|
@ -251,9 +250,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->instmem.unbind = nv50_instmem_unbind;
|
||||
engine->mc.init = nv50_mc_init;
|
||||
engine->mc.takedown = nv50_mc_takedown;
|
||||
engine->timer.init = nouveau_stub_init;
|
||||
engine->timer.read = nouveau_stub_timer_read;
|
||||
engine->timer.takedown = nouveau_stub_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
engine->timer.read = nv04_timer_read;
|
||||
engine->timer.takedown = nv04_timer_takedown;
|
||||
engine->fb.init = nouveau_stub_init;
|
||||
engine->fb.takedown = nouveau_stub_takedown;
|
||||
engine->graph.init = nv50_graph_init;
|
||||
|
|
@ -285,9 +284,6 @@ nouveau_card_init(struct drm_device *dev)
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine *engine;
|
||||
int ret;
|
||||
#if defined(__powerpc__)
|
||||
struct device_node *dn;
|
||||
#endif
|
||||
|
||||
DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
|
||||
|
||||
|
|
@ -295,43 +291,6 @@ nouveau_card_init(struct drm_device *dev)
|
|||
return 0;
|
||||
dev_priv->ttm = 0;
|
||||
|
||||
/* Map any PCI resources we need on the card */
|
||||
ret = nouveau_init_card_mappings(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
#if defined(__powerpc__)
|
||||
/* Put the card in BE mode if it's not */
|
||||
if (NV_READ(NV03_PMC_BOOT_1))
|
||||
NV_WRITE(NV03_PMC_BOOT_1,0x00000001);
|
||||
|
||||
DRM_MEMORYBARRIER();
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__powerpc__)
|
||||
/* if we have an OF card, copy vbios to RAMIN */
|
||||
dn = pci_device_to_OF_node(dev->pdev);
|
||||
if (dn)
|
||||
{
|
||||
int size;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
|
||||
const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size);
|
||||
#else
|
||||
const uint32_t *bios = get_property(dn, "NVDA,BMP", &size);
|
||||
#endif
|
||||
if (bios)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<size;i+=4)
|
||||
NV_WI32(i, bios[i/4]);
|
||||
DRM_INFO("OF bios successfully copied (%d bytes)\n",size);
|
||||
}
|
||||
else
|
||||
DRM_INFO("Unable to get the OF bios\n");
|
||||
}
|
||||
else
|
||||
DRM_INFO("Unable to get the OF node\n");
|
||||
#endif
|
||||
|
||||
/* Determine exact chipset we're running on */
|
||||
if (dev_priv->card_type < NV_10)
|
||||
dev_priv->chipset = dev_priv->card_type;
|
||||
|
|
@ -451,6 +410,47 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
|
|||
/* first module load, setup the mmio/fb mapping */
|
||||
int nouveau_firstopen(struct drm_device *dev)
|
||||
{
|
||||
#if defined(__powerpc__)
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct device_node *dn;
|
||||
#endif
|
||||
int ret;
|
||||
/* Map any PCI resources we need on the card */
|
||||
ret = nouveau_init_card_mappings(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
#if defined(__powerpc__)
|
||||
/* Put the card in BE mode if it's not */
|
||||
if (NV_READ(NV03_PMC_BOOT_1))
|
||||
NV_WRITE(NV03_PMC_BOOT_1,0x00000001);
|
||||
|
||||
DRM_MEMORYBARRIER();
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__powerpc__)
|
||||
/* if we have an OF card, copy vbios to RAMIN */
|
||||
dn = pci_device_to_OF_node(dev->pdev);
|
||||
if (dn)
|
||||
{
|
||||
int size;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
|
||||
const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size);
|
||||
#else
|
||||
const uint32_t *bios = get_property(dn, "NVDA,BMP", &size);
|
||||
#endif
|
||||
if (bios)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<size;i+=4)
|
||||
NV_WI32(i, bios[i/4]);
|
||||
DRM_INFO("OF bios successfully copied (%d bytes)\n",size);
|
||||
}
|
||||
else
|
||||
DRM_INFO("Unable to get the OF bios\n");
|
||||
}
|
||||
else
|
||||
DRM_INFO("Unable to get the OF node\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +498,12 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
iounmap(regs);
|
||||
|
||||
if (architecture >= 0x50) {
|
||||
if (architecture >= 0x80) {
|
||||
dev_priv->card_type = NV_50;
|
||||
} else if (architecture >= 0x60) {
|
||||
/* FIXME we need to figure out who's who for NV6x */
|
||||
dev_priv->card_type = NV_44;
|
||||
} else if (architecture >= 0x50) {
|
||||
dev_priv->card_type = NV_50;
|
||||
} else if (architecture >= 0x40) {
|
||||
uint8_t subarch = architecture & 0xf;
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ int nv04_graph_init(struct drm_device *dev) {
|
|||
/*haiku same*/
|
||||
|
||||
/*NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x10d4ff31);
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
|
||||
/*haiku and blob 10d4*/
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_STATE , 0xFFFFFFFF);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,25 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -432,19 +432,6 @@ static void nv30_31_graph_context_init(struct drm_device *dev,
|
|||
INSTANCE_WR(ctx, 0x385c/4, 0x3f800000);
|
||||
INSTANCE_WR(ctx, 0x3864/4, 0xbf800000);
|
||||
INSTANCE_WR(ctx, 0x386c/4, 0xbf800000);
|
||||
|
||||
/* nv30gl stuff */
|
||||
for (i=0; i<8; i++) {
|
||||
INSTANCE_WR(ctx, (0x4dfc/4)+i, 0x001c527d);
|
||||
}
|
||||
INSTANCE_WR(ctx, 0x4e3c/4, 0x001c527c);
|
||||
/* these ones make dma fifo hang
|
||||
INSTANCE_WR(ctx, 0x567c/4, 0x000a0000);
|
||||
INSTANCE_WR(ctx, 0x0878/4, 0x01000000);
|
||||
INSTANCE_WR(ctx, 0x02f4/4, 0x0001ffff);
|
||||
|
||||
INSTANCE_WR(ctx, 0x0028/4, INSTANCE_RD(ctx, 0x0028/4) | 1);
|
||||
*/
|
||||
}
|
||||
|
||||
static void nv34_graph_context_init(struct drm_device *dev,
|
||||
|
|
@ -655,6 +642,7 @@ int nv20_graph_load_context(struct nouveau_channel *chan)
|
|||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
|
||||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER,
|
||||
NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
return 0;
|
||||
|
|
@ -772,7 +760,7 @@ int nv20_graph_init(struct drm_device *dev) {
|
|||
NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00EA000C);
|
||||
NV_WRITE(NV10_PGRAPH_RDI_DATA, NV_READ(0x100324));
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000100);
|
||||
NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001);
|
||||
|
||||
|
|
@ -867,7 +855,7 @@ int nv30_graph_init(struct drm_device *dev)
|
|||
NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
|
||||
}
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000100);
|
||||
NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@
|
|||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
|
||||
typedef struct {
|
||||
struct nouveau_gpuobj_ref *thingo;
|
||||
} nv50_fifo_priv;
|
||||
struct nv50_fifo_priv {
|
||||
struct nouveau_gpuobj_ref *thingo[2];
|
||||
int cur_thingo;
|
||||
};
|
||||
|
||||
#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
|
||||
|
||||
|
|
@ -38,23 +39,23 @@ static void
|
|||
nv50_fifo_init_thingo(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
|
||||
struct nouveau_gpuobj_ref *thingo = priv->thingo;
|
||||
int i, fi=2;
|
||||
struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
|
||||
struct nouveau_gpuobj_ref *cur;
|
||||
int i, nr;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
INSTANCE_WR(thingo->gpuobj, 0, 0x7e);
|
||||
INSTANCE_WR(thingo->gpuobj, 1, 0x7e);
|
||||
for (i = 1; i < 127; i++, fi) {
|
||||
cur = priv->thingo[priv->cur_thingo];
|
||||
priv->cur_thingo = !priv->cur_thingo;
|
||||
|
||||
/* We never schedule channel 0 or 127 */
|
||||
for (i = 1, nr = 0; i < 127; i++) {
|
||||
if (dev_priv->fifos[i]) {
|
||||
INSTANCE_WR(thingo->gpuobj, fi, i);
|
||||
fi++;
|
||||
INSTANCE_WR(cur->gpuobj, nr++, i);
|
||||
}
|
||||
}
|
||||
|
||||
NV_WRITE(0x32f4, thingo->instance >> 12);
|
||||
NV_WRITE(0x32ec, fi);
|
||||
NV_WRITE(0x32f4, cur->instance >> 12);
|
||||
NV_WRITE(0x32ec, nr);
|
||||
NV_WRITE(0x2500, 0x101);
|
||||
}
|
||||
|
||||
|
|
@ -98,14 +99,12 @@ static void
|
|||
nv50_fifo_init_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t pmc_e;
|
||||
uint32_t pmc_e = NV_PMC_ENABLE_PFIFO;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
pmc_e = NV_READ(NV03_PMC_ENABLE);
|
||||
NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO);
|
||||
pmc_e = NV_READ(NV03_PMC_ENABLE);
|
||||
NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO);
|
||||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e);
|
||||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | pmc_e);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -141,7 +140,7 @@ nv50_fifo_init_regs__nv(struct drm_device *dev)
|
|||
NV_WRITE(0x250c, 0x6f3cfc34);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
nv50_fifo_init_regs(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
|
@ -158,15 +157,13 @@ nv50_fifo_init_regs(struct drm_device *dev)
|
|||
/* Enable dummy channels setup by nv50_instmem.c */
|
||||
nv50_fifo_channel_enable(dev, 0, 1);
|
||||
nv50_fifo_channel_enable(dev, 127, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fifo_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_fifo_priv *priv;
|
||||
struct nv50_fifo_priv *priv;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
|
@ -179,18 +176,23 @@ nv50_fifo_init(struct drm_device *dev)
|
|||
nv50_fifo_init_reset(dev);
|
||||
nv50_fifo_init_intr(dev);
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&priv->thingo))) {
|
||||
DRM_ERROR("error creating thingo: %d\n", ret);
|
||||
ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]);
|
||||
if (ret) {
|
||||
DRM_ERROR("error creating thingo0: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]);
|
||||
if (ret) {
|
||||
DRM_ERROR("error creating thingo1: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nv50_fifo_init_context_table(dev);
|
||||
|
||||
nv50_fifo_init_regs__nv(dev);
|
||||
if ((ret = nv50_fifo_init_regs(dev)))
|
||||
return ret;
|
||||
nv50_fifo_init_regs(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -199,14 +201,15 @@ void
|
|||
nv50_fifo_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
|
||||
struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &priv->thingo);
|
||||
nouveau_gpuobj_ref_del(dev, &priv->thingo[0]);
|
||||
nouveau_gpuobj_ref_del(dev, &priv->thingo[1]);
|
||||
|
||||
dev_priv->Engine.fifo.priv = NULL;
|
||||
drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
|
||||
|
|
@ -234,18 +237,18 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
if (IS_G80) {
|
||||
uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
|
||||
uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start;
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset,
|
||||
vram_offset, 0x100,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&ramfc, &chan->ramfc)))
|
||||
return ret;
|
||||
ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, vram_offset,
|
||||
0x100, NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE, &ramfc,
|
||||
&chan->ramfc);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100,
|
||||
256,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&chan->ramfc)))
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&chan->ramfc);
|
||||
if (ret)
|
||||
return ret;
|
||||
ramfc = chan->ramfc->gpuobj;
|
||||
}
|
||||
|
|
@ -272,7 +275,8 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
|
||||
}
|
||||
|
||||
if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) {
|
||||
ret = nv50_fifo_channel_enable(dev, chan->id, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -34,14 +34,12 @@ static void
|
|||
nv50_graph_init_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t pmc_e;
|
||||
uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
pmc_e = NV_READ(NV03_PMC_ENABLE);
|
||||
NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PGRAPH);
|
||||
pmc_e = NV_READ(NV03_PMC_ENABLE);
|
||||
NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH);
|
||||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e);
|
||||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | pmc_e);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -51,6 +49,7 @@ nv50_graph_init_intr(struct drm_device *dev)
|
|||
|
||||
DRM_DEBUG("\n");
|
||||
NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff);
|
||||
NV_WRITE(0x400138, 0xffffffff);
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff);
|
||||
}
|
||||
|
||||
|
|
@ -146,12 +145,53 @@ static uint32_t nv84_ctx_voodoo[] = {
|
|||
0x00415e06, 0x00415f05, 0x0060000d, 0x00700005, 0x0070000d, 0x00700006,
|
||||
0x0070000b, 0x0070000e, 0x0070001c, 0x0060000c, ~0
|
||||
};
|
||||
|
||||
static uint32_t nv86_ctx_voodoo[] = {
|
||||
0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89,
|
||||
0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff,
|
||||
0x00700009, 0x0040dd4d, 0x00402944, 0x00402905, 0x0040290d, 0x0040b906,
|
||||
0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000,
|
||||
0x00700081, 0x00600004, 0x0050004a, 0x00216d80, 0x00600007, 0x00c02801,
|
||||
0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020,
|
||||
0x00600008, 0x0050004c, 0x00600009, 0x0040b945, 0x0040d44d, 0x0070009d,
|
||||
0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008,
|
||||
0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006,
|
||||
0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216d80, 0x00600007,
|
||||
0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080,
|
||||
0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200280, 0x00600007,
|
||||
0x00300000, 0x00c000ff, 0x00c800ff, 0x0040c407, 0x00202916, 0x008000ff,
|
||||
0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f,
|
||||
0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302,
|
||||
0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f,
|
||||
0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02,
|
||||
0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407,
|
||||
0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b,
|
||||
0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x0070008f, 0x0040798c,
|
||||
0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04,
|
||||
0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65,
|
||||
0x00131f00, 0x00191f40, 0x004099e0, 0x002001d9, 0x00600006, 0x00200044,
|
||||
0x00102080, 0x001120c6, 0x001520c9, 0x001920d0, 0x00122100, 0x00122103,
|
||||
0x00162200, 0x00122207, 0x00112280, 0x00112300, 0x00112302, 0x00122380,
|
||||
0x0011238b, 0x00112394, 0x0011239c, 0x00000000, 0x0040a00f, 0x005000cb,
|
||||
0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x005000cb, 0x0040a387,
|
||||
0x0060000a, 0x00000000, 0x0040b200, 0x007000a0, 0x00700080, 0x00200280,
|
||||
0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb, 0x00700000,
|
||||
0x00200000, 0x00600006, 0x00111bfe, 0x0040d44d, 0x00700000, 0x00200000,
|
||||
0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d, 0x00700081,
|
||||
0x00600004, 0x0050004a, 0x0040be88, 0x0060000b, 0x00200000, 0x00600006,
|
||||
0x00700000, 0x0040d40b, 0x00111bfd, 0x0040424d, 0x00202916, 0x008000fd,
|
||||
0x005000cb, 0x00c00002, 0x00200280, 0x00600007, 0x00200160, 0x00800002,
|
||||
0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb, 0x00404e4d,
|
||||
0x0060000b, 0x0040d24d, 0x00700001, 0x00700003, 0x0040d806, 0x0040d905,
|
||||
0x0060000d, 0x00700005, 0x0070000d, 0x00700006, 0x0070000b, 0x0070000e,
|
||||
0x0070001c, 0x0060000c, ~0
|
||||
};
|
||||
|
||||
static void
|
||||
static int
|
||||
nv50_graph_init_ctxctl(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t *voodoo;
|
||||
uint32_t *voodoo = NULL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
|
|
@ -159,34 +199,42 @@ nv50_graph_init_ctxctl(struct drm_device *dev)
|
|||
case 0x84:
|
||||
voodoo = nv84_ctx_voodoo;
|
||||
break;
|
||||
case 0x86:
|
||||
voodoo = nv86_ctx_voodoo;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset);
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (voodoo) {
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
|
||||
while (*voodoo != ~0) {
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo);
|
||||
voodoo++;
|
||||
}
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
|
||||
while (*voodoo != ~0) {
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo);
|
||||
voodoo++;
|
||||
}
|
||||
|
||||
NV_WRITE(0x400320, 4);
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0);
|
||||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_graph_init(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
nv50_graph_init_reset(dev);
|
||||
nv50_graph_init_intr(dev);
|
||||
nv50_graph_init_regs__nv(dev);
|
||||
nv50_graph_init_regs(dev);
|
||||
nv50_graph_init_ctxctl(dev);
|
||||
|
||||
ret = nv50_graph_init_ctxctl(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -209,11 +257,10 @@ nv50_graph_create_context(struct nouveau_channel *chan)
|
|||
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0,
|
||||
grctx_size, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&chan->ramin_grctx)))
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = IS_G80 ? 0x200 : 0x20;
|
||||
|
|
@ -225,11 +272,16 @@ nv50_graph_create_context(struct nouveau_channel *chan)
|
|||
INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
|
||||
INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
|
||||
|
||||
if ((ret = engine->graph.load_context(chan))) {
|
||||
ret = engine->graph.load_context(chan);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error hacking up initial context: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x00000/4,
|
||||
chan->ramin->instance >> 12);
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x0011c/4, 0x00000002);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +311,7 @@ nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
|
|||
DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save);
|
||||
|
||||
old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
|
||||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst | (1<<31));
|
||||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
|
||||
NV_WRITE(0x400824, NV_READ(0x400824) |
|
||||
(save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
|
||||
NV40_PGRAPH_CTXCTL_0310_XFER_LOAD));
|
||||
|
|
@ -286,7 +338,7 @@ nv50_graph_load_context(struct nouveau_channel *chan)
|
|||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
|
||||
uint32_t inst = chan->ramin->instance >> 12;
|
||||
int ret; (void)ret;
|
||||
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
|
@ -298,7 +350,7 @@ nv50_graph_load_context(struct nouveau_channel *chan)
|
|||
|
||||
NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
|
||||
NV_WRITE(0x400320, 4);
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst);
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst | (1<<31));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -307,7 +359,7 @@ int
|
|||
nv50_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
|
||||
uint32_t inst = chan->ramin->instance >> 12;
|
||||
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ nv50_instmem_init(struct drm_device *dev)
|
|||
return -ENOMEM;
|
||||
dev_priv->Engine.instmem.priv = priv;
|
||||
|
||||
/* Save state, will restore at takedown. */
|
||||
for (i = 0x1700; i <= 0x1710; i+=4)
|
||||
priv->save1700[(i-0x1700)/4] = NV_READ(i);
|
||||
|
||||
/* Reserve the last MiB of VRAM, we should probably try to avoid
|
||||
* setting up the below tables over the top of the VBIOS image at
|
||||
* some point.
|
||||
|
|
|
|||
|
|
@ -649,7 +649,7 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
|
||||
DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
|
||||
DRM_DEBUG("while CCE running\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +708,7 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_DEBUG("%s called before init done\n", __FUNCTION__);
|
||||
DRM_DEBUG("called before init done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ typedef struct drm_r128_private {
|
|||
u32 crtc_offset;
|
||||
u32 crtc_offset_cntl;
|
||||
|
||||
atomic_t vbl_received;
|
||||
|
||||
u32 color_fmt;
|
||||
unsigned int front_offset;
|
||||
unsigned int front_pitch;
|
||||
|
|
@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
|
|||
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
|
||||
extern int r128_do_cleanup_cce(struct drm_device * dev);
|
||||
|
||||
extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
|
||||
extern int r128_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void r128_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void r128_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void r128_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern int r128_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void r128_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern void r128_driver_lastclose(struct drm_device * dev);
|
||||
extern void r128_driver_preclose(struct drm_device * dev,
|
||||
|
|
@ -462,8 +465,7 @@ do { \
|
|||
|
||||
#define BEGIN_RING( n ) do { \
|
||||
if ( R128_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
||||
(n), __FUNCTION__ ); \
|
||||
DRM_INFO( "BEGIN_RING( %d )\n", (n)); \
|
||||
} \
|
||||
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
|
||||
COMMIT_RING(); \
|
||||
|
|
|
|||
|
|
@ -35,6 +35,16 @@
|
|||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
|
||||
u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
const drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (crtc != 0)
|
||||
return 0;
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
|
|
@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
/* VBLANK interrupt */
|
||||
if (status & R128_CRTC_VBLANK_INT) {
|
||||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
drm_handle_vblank(dev, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
int r128_enable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r128_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
if (crtc != 0)
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
|
||||
/*
|
||||
* FIXME: implement proper interrupt disable by using the vblank
|
||||
* counter register (if available)
|
||||
*
|
||||
* R128_WRITE(R128_GEN_INT_CNTL,
|
||||
* R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void r128_driver_irq_preinstall(struct drm_device * dev)
|
||||
|
|
@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
|
|||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
}
|
||||
|
||||
void r128_driver_irq_postinstall(struct drm_device * dev)
|
||||
int r128_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
|
||||
/* Turn on VBL interrupt */
|
||||
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
|
||||
return drm_vblank_init(dev, 1);
|
||||
}
|
||||
|
||||
void r128_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
|
|||
{
|
||||
u32 aux_sc_cntl = 0x00000000;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(13);
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(3);
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(5);
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
|
|||
drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
|
|||
drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG(" %s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ static void r128_emit_state(drm_r128_private_t * dev_priv)
|
|||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
|
||||
DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
|
||||
DRM_DEBUG("dirty=0x%08x\n", dirty);
|
||||
|
||||
if (dirty & R128_UPLOAD_CORE) {
|
||||
r128_emit_core(dev_priv);
|
||||
|
|
@ -362,7 +362,7 @@ static void r128_cce_dispatch_clear(struct drm_device * dev,
|
|||
unsigned int flags = clear->flags;
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev_priv->page_flipping && dev_priv->current_page == 1) {
|
||||
unsigned int tmp = flags;
|
||||
|
|
@ -466,7 +466,7 @@ static void r128_cce_dispatch_swap(struct drm_device * dev)
|
|||
struct drm_clip_rect *pbox = sarea_priv->boxes;
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
#if R128_PERFORMANCE_BOXES
|
||||
/* Do some trivial performance monitoring...
|
||||
|
|
@ -528,8 +528,7 @@ static void r128_cce_dispatch_flip(struct drm_device * dev)
|
|||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("page=%d pfCurrentPage=%d\n",
|
||||
dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
|
||||
|
||||
#if R128_PERFORMANCE_BOXES
|
||||
|
|
@ -1156,7 +1155,7 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
|
|||
int count, *x, *y;
|
||||
int i, xbuf_size, ybuf_size;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
count = depth->n;
|
||||
if (count > 4096 || count <= 0)
|
||||
|
|
@ -1226,7 +1225,7 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
|
|||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(33);
|
||||
|
||||
|
|
@ -1309,7 +1308,7 @@ static int r128_do_cleanup_pageflip(struct drm_device * dev)
|
|||
static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1328,7 +1327,7 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
|
@ -1356,7 +1355,7 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1412,7 +1411,7 @@ static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -1557,11 +1556,11 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
|
||||
DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
|
||||
indirect->idx, indirect->start, indirect->end,
|
||||
indirect->discard);
|
||||
|
||||
|
|
@ -1622,7 +1621,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,23 +77,31 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
box.x1 =
|
||||
(box.x1 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.y1 =
|
||||
(box.y1 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.x2 =
|
||||
(box.x2 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.y2 =
|
||||
(box.y2 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
|
||||
box.x1 = (box.x1) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.y1 = (box.y1) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.x2 = (box.x2) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.y2 = (box.y2) &
|
||||
R300_CLIPRECT_MASK;
|
||||
} else {
|
||||
box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
|
||||
R300_CLIPRECT_MASK;
|
||||
box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
|
||||
R300_CLIPRECT_MASK;
|
||||
|
||||
}
|
||||
OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
|
||||
(box.y1 << R300_CLIPRECT_Y_SHIFT));
|
||||
OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
|
||||
(box.y2 << R300_CLIPRECT_Y_SHIFT));
|
||||
|
||||
}
|
||||
|
||||
OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
|
||||
|
|
@ -133,9 +141,11 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
|||
|
||||
static u8 r300_reg_flags[0x10000 >> 2];
|
||||
|
||||
void r300_init_reg_flags(void)
|
||||
void r300_init_reg_flags(struct drm_device *dev)
|
||||
{
|
||||
int i;
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
memset(r300_reg_flags, 0, 0x10000 >> 2);
|
||||
#define ADD_RANGE_MARK(reg, count,mark) \
|
||||
for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
|
||||
|
|
@ -230,6 +240,9 @@ void r300_init_reg_flags(void)
|
|||
ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
|
||||
ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
|
||||
ADD_RANGE(0x4074, 16);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ int r300_check_range(unsigned reg, int count)
|
||||
|
|
|
|||
|
|
@ -816,19 +816,44 @@ static const u32 R300_cp_microcode[][2] = {
|
|||
{ 0000000000, 0000000000 },
|
||||
};
|
||||
|
||||
static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
|
||||
{
|
||||
u32 ret;
|
||||
RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
|
||||
ret = RADEON_READ(R520_MC_IND_DATA);
|
||||
RADEON_WRITE(R520_MC_IND_INDEX, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
return RADEON_READ(RADEON_MC_FB_LOCATION);
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
|
||||
return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
|
||||
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
|
||||
return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
|
||||
else
|
||||
return RADEON_READ(RADEON_MC_FB_LOCATION);
|
||||
}
|
||||
|
||||
static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
|
||||
{
|
||||
RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
|
||||
RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
|
||||
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
|
||||
RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
|
||||
else
|
||||
RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
|
||||
}
|
||||
|
||||
static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
|
||||
{
|
||||
RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
|
||||
RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
|
||||
else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
|
||||
RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
|
||||
else
|
||||
RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
|
||||
}
|
||||
|
||||
static int RADEON_READ_PLL(struct drm_device * dev, int addr)
|
||||
|
|
@ -1089,41 +1114,43 @@ static int radeon_do_engine_reset(struct drm_device * dev)
|
|||
|
||||
radeon_do_pixcache_flush(dev_priv);
|
||||
|
||||
clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
|
||||
mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
|
||||
|
||||
RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
|
||||
RADEON_FORCEON_MCLKA |
|
||||
RADEON_FORCEON_MCLKB |
|
||||
RADEON_FORCEON_YCLKA |
|
||||
RADEON_FORCEON_YCLKB |
|
||||
RADEON_FORCEON_MC |
|
||||
RADEON_FORCEON_AIC));
|
||||
|
||||
rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
|
||||
RADEON_SOFT_RESET_CP |
|
||||
RADEON_SOFT_RESET_HI |
|
||||
RADEON_SOFT_RESET_SE |
|
||||
RADEON_SOFT_RESET_RE |
|
||||
RADEON_SOFT_RESET_PP |
|
||||
RADEON_SOFT_RESET_E2 |
|
||||
RADEON_SOFT_RESET_RB));
|
||||
RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
|
||||
~(RADEON_SOFT_RESET_CP |
|
||||
RADEON_SOFT_RESET_HI |
|
||||
RADEON_SOFT_RESET_SE |
|
||||
RADEON_SOFT_RESET_RE |
|
||||
RADEON_SOFT_RESET_PP |
|
||||
RADEON_SOFT_RESET_E2 |
|
||||
RADEON_SOFT_RESET_RB)));
|
||||
RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
|
||||
RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
|
||||
RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
|
||||
clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
|
||||
mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
|
||||
|
||||
RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
|
||||
RADEON_FORCEON_MCLKA |
|
||||
RADEON_FORCEON_MCLKB |
|
||||
RADEON_FORCEON_YCLKA |
|
||||
RADEON_FORCEON_YCLKB |
|
||||
RADEON_FORCEON_MC |
|
||||
RADEON_FORCEON_AIC));
|
||||
|
||||
rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
|
||||
RADEON_SOFT_RESET_CP |
|
||||
RADEON_SOFT_RESET_HI |
|
||||
RADEON_SOFT_RESET_SE |
|
||||
RADEON_SOFT_RESET_RE |
|
||||
RADEON_SOFT_RESET_PP |
|
||||
RADEON_SOFT_RESET_E2 |
|
||||
RADEON_SOFT_RESET_RB));
|
||||
RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
|
||||
~(RADEON_SOFT_RESET_CP |
|
||||
RADEON_SOFT_RESET_HI |
|
||||
RADEON_SOFT_RESET_SE |
|
||||
RADEON_SOFT_RESET_RE |
|
||||
RADEON_SOFT_RESET_PP |
|
||||
RADEON_SOFT_RESET_E2 |
|
||||
RADEON_SOFT_RESET_RB)));
|
||||
RADEON_READ(RADEON_RBBM_SOFT_RESET);
|
||||
|
||||
RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
|
||||
RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
|
||||
RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
|
||||
}
|
||||
|
||||
/* Reset the CP ring */
|
||||
radeon_do_cp_reset(dev_priv);
|
||||
|
|
@ -1881,7 +1908,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (init->func == RADEON_INIT_R300_CP)
|
||||
r300_init_reg_flags();
|
||||
r300_init_reg_flags(dev);
|
||||
|
||||
switch (init->func) {
|
||||
case RADEON_INIT_CP:
|
||||
|
|
@ -1903,12 +1930,12 @@ int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (dev_priv->cp_running) {
|
||||
DRM_DEBUG("%s while CP running\n", __FUNCTION__);
|
||||
DRM_DEBUG("while CP running\n");
|
||||
return 0;
|
||||
}
|
||||
if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
|
||||
DRM_DEBUG("%s called with bogus CP mode (%d)\n",
|
||||
__FUNCTION__, dev_priv->cp_mode);
|
||||
DRM_DEBUG("called with bogus CP mode (%d)\n",
|
||||
dev_priv->cp_mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2018,7 +2045,7 @@ int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_DEBUG("%s called before init done\n", __FUNCTION__);
|
||||
DRM_DEBUG("called before init done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2295,6 +2322,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
case CHIP_R350:
|
||||
case CHIP_R420:
|
||||
case CHIP_RV410:
|
||||
case CHIP_RV515:
|
||||
case CHIP_R520:
|
||||
case CHIP_RV570:
|
||||
case CHIP_R580:
|
||||
dev_priv->flags |= RADEON_HAS_HIERZ;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -129,6 +129,12 @@ enum radeon_family {
|
|||
CHIP_R420,
|
||||
CHIP_RV410,
|
||||
CHIP_RS400,
|
||||
CHIP_RV515,
|
||||
CHIP_R520,
|
||||
CHIP_RV530,
|
||||
CHIP_RV560,
|
||||
CHIP_RV570,
|
||||
CHIP_R580,
|
||||
CHIP_LAST,
|
||||
};
|
||||
|
||||
|
|
@ -305,6 +311,9 @@ typedef struct drm_radeon_private {
|
|||
|
||||
u32 scratch_ages[5];
|
||||
|
||||
unsigned int crtc_last_cnt;
|
||||
unsigned int crtc2_last_cnt;
|
||||
|
||||
/* starting from here on, data is preserved accross an open */
|
||||
uint32_t flags; /* see radeon_chip_flags */
|
||||
unsigned long fb_aper_offset;
|
||||
|
|
@ -374,13 +383,13 @@ extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *
|
|||
extern int radeon_emit_irq(struct drm_device * dev);
|
||||
|
||||
extern void radeon_do_release(struct drm_device * dev);
|
||||
extern int radeon_driver_vblank_wait(struct drm_device * dev,
|
||||
unsigned int *sequence);
|
||||
extern int radeon_driver_vblank_wait2(struct drm_device * dev,
|
||||
unsigned int *sequence);
|
||||
extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void radeon_do_release(struct drm_device * dev);
|
||||
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void radeon_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void radeon_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern int radeon_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void radeon_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern int radeon_vblank_crtc_get(struct drm_device *dev);
|
||||
extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
|
||||
|
|
@ -399,7 +408,7 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
|
|||
unsigned long arg);
|
||||
|
||||
/* r300_cmdbuf.c */
|
||||
extern void r300_init_reg_flags(void);
|
||||
extern void r300_init_reg_flags(struct drm_device *dev);
|
||||
|
||||
extern int r300_do_cp_cmdbuf(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
|
|
@ -423,7 +432,7 @@ extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t
|
|||
extern struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device *dev);
|
||||
extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type);
|
||||
extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
|
||||
extern uint32_t radeon_evict_mask(struct drm_buffer_object *bo);
|
||||
extern uint64_t radeon_evict_flags(struct drm_buffer_object *bo);
|
||||
extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
|
||||
struct drm_mem_type_manager * man);
|
||||
extern int radeon_move(struct drm_buffer_object * bo,
|
||||
|
|
@ -494,6 +503,15 @@ extern int radeon_move(struct drm_buffer_object * bo,
|
|||
#define RADEON_IGPGART_ENABLE 0x38
|
||||
#define RADEON_IGPGART_UNK_39 0x39
|
||||
|
||||
#define R520_MC_IND_INDEX 0x70
|
||||
#define R520_MC_IND_WR_EN (1<<24)
|
||||
#define R520_MC_IND_DATA 0x74
|
||||
|
||||
#define RV515_MC_FB_LOCATION 0x01
|
||||
#define RV515_MC_AGP_LOCATION 0x02
|
||||
|
||||
#define R520_MC_FB_LOCATION 0x04
|
||||
#define R520_MC_AGP_LOCATION 0x05
|
||||
|
||||
#define RADEON_MPP_TB_CONFIG 0x01c0
|
||||
#define RADEON_MEM_CNTL 0x0140
|
||||
|
|
@ -545,6 +563,12 @@ extern int radeon_move(struct drm_buffer_object * bo,
|
|||
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
|
||||
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
|
||||
|
||||
#define RADEON_CRTC_CRNT_FRAME 0x0214
|
||||
#define RADEON_CRTC2_CRNT_FRAME 0x0314
|
||||
|
||||
#define RADEON_CRTC_STATUS 0x005c
|
||||
#define RADEON_CRTC2_STATUS 0x03fc
|
||||
|
||||
#define RADEON_GEN_INT_CNTL 0x0040
|
||||
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
|
||||
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
|
||||
|
|
@ -1117,6 +1141,13 @@ do { \
|
|||
RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \
|
||||
} while (0)
|
||||
|
||||
#define RADEON_WRITE_MCIND( addr, val ) \
|
||||
do { \
|
||||
RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \
|
||||
RADEON_WRITE(R520_MC_IND_DATA, (val)); \
|
||||
RADEON_WRITE(R520_MC_IND_INDEX, 0); \
|
||||
} while (0)
|
||||
|
||||
#define CP_PACKET0( reg, n ) \
|
||||
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
|
||||
#define CP_PACKET0_TABLE( reg, n ) \
|
||||
|
|
@ -1227,8 +1258,7 @@ do { \
|
|||
|
||||
#define BEGIN_RING( n ) do { \
|
||||
if ( RADEON_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
||||
n, __FUNCTION__ ); \
|
||||
DRM_INFO( "BEGIN_RING( %d )\n", (n)); \
|
||||
} \
|
||||
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
|
||||
COMMIT_RING(); \
|
||||
|
|
|
|||
|
|
@ -35,12 +35,61 @@
|
|||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
|
||||
u32 mask)
|
||||
static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
|
||||
{
|
||||
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (state)
|
||||
dev_priv->irq_enable_reg |= mask;
|
||||
else
|
||||
dev_priv->irq_enable_reg &= ~mask;
|
||||
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
|
||||
}
|
||||
|
||||
int radeon_enable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
|
||||
break;
|
||||
case 1:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
|
||||
break;
|
||||
case 1:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
|
||||
{
|
||||
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
|
||||
(RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT);
|
||||
|
||||
if (irqs)
|
||||
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
|
||||
|
||||
return irqs;
|
||||
}
|
||||
|
||||
|
|
@ -72,9 +121,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
/* Only consider the bits we're interested in - others could be used
|
||||
* outside the DRM
|
||||
*/
|
||||
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT));
|
||||
stat = radeon_acknowledge_irqs(dev_priv);
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
|
|
@ -87,27 +134,11 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
radeon_fence_handler(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
|
||||
int vblank_crtc = dev_priv->vblank_crtc;
|
||||
|
||||
if ((vblank_crtc &
|
||||
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
|
||||
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
|
||||
if (stat & RADEON_CRTC_VBLANK_STAT)
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (stat & RADEON_CRTC2_VBLANK_STAT)
|
||||
atomic_inc(&dev->vbl_received2);
|
||||
} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
|
||||
(vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
|
||||
((stat & RADEON_CRTC2_VBLANK_STAT) &&
|
||||
(vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
|
||||
atomic_inc(&dev->vbl_received);
|
||||
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
}
|
||||
if (stat & RADEON_CRTC_VBLANK_STAT)
|
||||
drm_handle_vblank(dev, 0);
|
||||
if (stat & RADEON_CRTC2_VBLANK_STAT)
|
||||
drm_handle_vblank(dev, 1);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
@ -146,54 +177,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_driver_vblank_do_wait(struct drm_device * dev,
|
||||
unsigned int *sequence, int crtc)
|
||||
u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
int ack = 0;
|
||||
atomic_t *counter;
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
u32 crtc_cnt_reg, crtc_status_reg;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crtc == DRM_RADEON_VBLANK_CRTC1) {
|
||||
counter = &dev->vbl_received;
|
||||
ack |= RADEON_CRTC_VBLANK_STAT;
|
||||
} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
|
||||
counter = &dev->vbl_received2;
|
||||
ack |= RADEON_CRTC2_VBLANK_STAT;
|
||||
} else
|
||||
if (crtc == 0) {
|
||||
crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
|
||||
crtc_status_reg = RADEON_CRTC_STATUS;
|
||||
} else if (crtc == 1) {
|
||||
crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
|
||||
crtc_status_reg = RADEON_CRTC2_STATUS;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
radeon_acknowledge_irqs(dev_priv, ack);
|
||||
|
||||
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(counter))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
|
||||
}
|
||||
|
||||
int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
|
||||
return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
|
|
@ -207,7 +211,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -229,28 +233,13 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
drm_radeon_irq_wait_t *irqwait = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return radeon_wait_irq(dev, irqwait->irq_seq);
|
||||
}
|
||||
|
||||
static void radeon_enable_interrupt(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
|
||||
|
||||
dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
|
||||
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
|
||||
dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
|
||||
|
||||
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
|
||||
dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
|
||||
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
|
||||
dev_priv->irq_enabled = 1;
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void radeon_driver_irq_preinstall(struct drm_device * dev)
|
||||
|
|
@ -262,20 +251,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
|
|||
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
|
||||
|
||||
/* Clear bits if they're already high */
|
||||
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT));
|
||||
radeon_acknowledge_irqs(dev_priv);
|
||||
}
|
||||
|
||||
void radeon_driver_irq_postinstall(struct drm_device * dev)
|
||||
int radeon_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
int ret;
|
||||
|
||||
dev_priv->counter = 0;
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
||||
radeon_enable_interrupt(dev);
|
||||
ret = drm_vblank_init(dev, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->max_vblank_count = 0x001fffff;
|
||||
|
||||
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
|
@ -317,6 +313,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
|
|||
return -EINVAL;
|
||||
}
|
||||
dev_priv->vblank_crtc = (unsigned int)value;
|
||||
radeon_enable_interrupt(dev);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p
|
|||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
struct mem_block *block, **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +285,7 @@ int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
struct mem_block **heap;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ int radeon_ms_bo_get_gpu_addr(struct drm_device *dev,
|
|||
int radeon_ms_bo_move(struct drm_buffer_object * bo, int evict,
|
||||
int no_wait, struct drm_bo_mem_reg * new_mem);
|
||||
struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev);
|
||||
uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo);
|
||||
uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo);
|
||||
int radeon_ms_init_mem_type(struct drm_device * dev, uint32_t type,
|
||||
struct drm_mem_type_manager * man);
|
||||
int radeon_ms_invalidate_caches(struct drm_device * dev, uint64_t flags);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static int radeon_ms_bo_move_flip(struct drm_buffer_object *bo,
|
|||
|
||||
tmp_mem = *new_mem;
|
||||
tmp_mem.mm_node = NULL;
|
||||
tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
|
||||
tmp_mem.flags = DRM_BO_FLAG_MEM_TT |
|
||||
DRM_BO_FLAG_CACHED |
|
||||
DRM_BO_FLAG_FORCE_CACHING;
|
||||
ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
|
||||
|
|
@ -149,7 +149,7 @@ static int radeon_ms_bo_move_flip(struct drm_buffer_object *bo,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_bind_ttm(bo->ttm, &tmp_mem);
|
||||
ret = drm_ttm_bind(bo->ttm, &tmp_mem);
|
||||
if (ret) {
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
|
@ -217,7 +217,7 @@ struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo)
|
||||
uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo)
|
||||
{
|
||||
switch (bo->mem.mem_type) {
|
||||
case DRM_BO_MEM_LOCAL:
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct drm_bo_driver radeon_ms_bo_driver = {
|
|||
.fence_type = radeon_ms_fence_types,
|
||||
.invalidate_caches = radeon_ms_invalidate_caches,
|
||||
.init_mem_type = radeon_ms_init_mem_type,
|
||||
.evict_mask = radeon_ms_evict_mask,
|
||||
.evict_flags = radeon_ms_evict_flags,
|
||||
.move = radeon_ms_bo_move,
|
||||
.ttm_cache_flush = radeon_ms_ttm_flush,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -898,7 +898,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
|
|||
int w = pbox[i].x2 - x;
|
||||
int h = pbox[i].y2 - y;
|
||||
|
||||
DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
|
||||
DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n",
|
||||
x, y, w, h, flags);
|
||||
|
||||
if (flags & RADEON_FRONT) {
|
||||
|
|
@ -1368,7 +1368,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
|
|||
int w = pbox[i].x2 - x;
|
||||
int h = pbox[i].y2 - y;
|
||||
|
||||
DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
|
||||
DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
|
||||
|
||||
BEGIN_RING(9);
|
||||
|
||||
|
|
@ -1422,8 +1422,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)
|
|||
int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
|
||||
? dev_priv->front_offset : dev_priv->back_offset;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s: pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
DRM_DEBUG("pfCurrentPage=%d\n",
|
||||
dev_priv->sarea_priv->pfCurrentPage);
|
||||
|
||||
/* Do some trivial performance monitoring...
|
||||
|
|
@ -1562,7 +1561,7 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev,
|
|||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
|
||||
DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
|
||||
|
||||
if (start != end) {
|
||||
int offset = (dev_priv->gart_buffers_offset
|
||||
|
|
@ -1758,7 +1757,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
|
|||
buf = radeon_freelist_get(dev);
|
||||
}
|
||||
if (!buf) {
|
||||
DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
|
||||
DRM_DEBUG("EAGAIN\n");
|
||||
if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
|
||||
return -EFAULT;
|
||||
return -EAGAIN;
|
||||
|
|
@ -2084,7 +2083,7 @@ static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_f
|
|||
drm_radeon_surface_alloc_t *alloc = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2100,7 +2099,7 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi
|
|||
drm_radeon_surface_free_t *memfree = data;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2215,7 +2214,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2299,7 +2298,7 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
sarea_priv = dev_priv->sarea_priv;
|
||||
|
|
@ -2437,11 +2436,11 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
|
||||
DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
|
||||
indirect->idx, indirect->start, indirect->end,
|
||||
indirect->discard);
|
||||
|
||||
|
|
@ -2509,7 +2508,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2814,7 +2813,7 @@ static int radeon_emit_wait(struct drm_device * dev, int flags)
|
|||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
|
||||
DRM_DEBUG("%x\n", flags);
|
||||
switch (flags) {
|
||||
case RADEON_WAIT_2D:
|
||||
BEGIN_RING(2);
|
||||
|
|
@ -2852,7 +2851,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -3013,7 +3012,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -3104,7 +3103,7 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
struct drm_radeon_driver_file_fields *radeon_priv;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,14 +167,12 @@ static int via_initialize(struct drm_device * dev,
|
|||
}
|
||||
|
||||
if (dev_priv->ring.virtual_start != NULL) {
|
||||
DRM_ERROR("%s called again without calling cleanup\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("called again without calling cleanup\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!dev->agp || !dev->agp->base) {
|
||||
DRM_ERROR("%s called with no agp memory available\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("called with no agp memory available\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
|
@ -257,8 +255,7 @@ static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t *
|
|||
dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start == NULL) {
|
||||
DRM_ERROR("%s called without initializing AGP ring buffer.\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("called without initializing AGP ring buffer.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
|
@ -327,8 +324,7 @@ static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf->buf,
|
||||
cmdbuf->size);
|
||||
DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
|
||||
|
||||
ret = via_dispatch_cmdbuffer(dev, cmdbuf);
|
||||
if (ret) {
|
||||
|
|
@ -369,8 +365,7 @@ static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf->buf,
|
||||
cmdbuf->size);
|
||||
DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
|
||||
|
||||
ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
|
||||
if (ret) {
|
||||
|
|
@ -640,14 +635,13 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
|
|||
uint32_t tmp_size, count;
|
||||
drm_via_private_t *dev_priv;
|
||||
|
||||
DRM_DEBUG("via cmdbuf_size\n");
|
||||
DRM_DEBUG("\n");
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start == NULL) {
|
||||
DRM_ERROR("%s called without initializing AGP ring buffer.\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("called without initializing AGP ring buffer.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static struct drm_bo_driver via_bo_driver = {
|
|||
.fence_type = via_fence_types,
|
||||
.invalidate_caches = via_invalidate_caches,
|
||||
.init_mem_type = via_init_mem_type,
|
||||
.evict_mask = via_evict_mask,
|
||||
.evict_flags = via_evict_flags,
|
||||
.move = NULL,
|
||||
};
|
||||
#endif
|
||||
|
|
@ -83,14 +83,16 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
|||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
|
||||
DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
|
||||
DRIVER_IRQ_SHARED,
|
||||
.load = via_driver_load,
|
||||
.unload = via_driver_unload,
|
||||
#ifndef VIA_HAVE_CORE_MM
|
||||
.context_ctor = via_init_context,
|
||||
#endif
|
||||
.context_dtor = via_final_context,
|
||||
.vblank_wait = via_driver_vblank_wait,
|
||||
.get_vblank_counter = via_get_vblank_counter,
|
||||
.enable_vblank = via_enable_vblank,
|
||||
.disable_vblank = via_disable_vblank,
|
||||
.irq_preinstall = via_driver_irq_preinstall,
|
||||
.irq_postinstall = via_driver_irq_postinstall,
|
||||
.irq_uninstall = via_driver_irq_uninstall,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ typedef struct drm_via_private {
|
|||
struct timeval last_vblank;
|
||||
int last_vblank_valid;
|
||||
unsigned usec_per_vblank;
|
||||
atomic_t vbl_received;
|
||||
drm_via_state_t hc_state;
|
||||
char pci_buf[VIA_PCI_BUF_SIZE];
|
||||
const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
|
||||
|
|
@ -166,11 +167,13 @@ extern int via_driver_unload(struct drm_device *dev);
|
|||
extern int via_final_context(struct drm_device * dev, int context);
|
||||
|
||||
extern int via_do_cleanup_map(struct drm_device * dev);
|
||||
extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int via_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void via_disable_vblank(struct drm_device *dev, int crtc);
|
||||
|
||||
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void via_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void via_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern int via_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void via_driver_irq_uninstall(struct drm_device * dev);
|
||||
|
||||
extern int via_dma_cleanup(struct drm_device * dev);
|
||||
|
|
@ -211,7 +214,7 @@ extern int via_fence_types(struct drm_buffer_object *bo, uint32_t *fclass,
|
|||
extern int via_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
|
||||
extern int via_init_mem_type(struct drm_device *dev, uint32_t type,
|
||||
struct drm_mem_type_manager *man);
|
||||
extern uint32_t via_evict_mask(struct drm_buffer_object *bo);
|
||||
extern uint64_t via_evict_flags(struct drm_buffer_object *bo);
|
||||
extern int via_move(struct drm_buffer_object *bo, int evict,
|
||||
int no_wait, struct drm_bo_mem_reg *new_mem);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -96,6 +96,15 @@ static unsigned time_diff(struct timeval *now,struct timeval *then)
|
|||
1000000 - (then->tv_usec - now->tv_usec);
|
||||
}
|
||||
|
||||
u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
if (crtc != 0)
|
||||
return 0;
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
|
|
@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
if (status & VIA_IRQ_VBLANK_PENDING) {
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
|
||||
#ifdef __linux__
|
||||
do_gettimeofday(&cur_vblank);
|
||||
#else
|
||||
|
|
@ -123,12 +132,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
dev_priv->last_vblank = cur_vblank;
|
||||
dev_priv->last_vblank_valid = 1;
|
||||
}
|
||||
if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
|
||||
if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
|
||||
DRM_DEBUG("US per vblank is: %u\n",
|
||||
dev_priv->usec_per_vblank);
|
||||
}
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
drm_handle_vblank(dev, 0);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
|
|
@ -170,31 +178,25 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
|
|||
}
|
||||
}
|
||||
|
||||
int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
int via_enable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
u32 status;
|
||||
|
||||
DRM_DEBUG("viadrv_vblank_wait\n");
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
viadrv_acknowledge_irqs(dev_priv);
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received)) -
|
||||
*sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
return ret;
|
||||
void via_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
if (crtc != 0)
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -208,24 +210,23 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc
|
|||
maskarray_t *masks;
|
||||
int real_irq;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (irq >= drm_via_irq_num) {
|
||||
DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
|
||||
irq);
|
||||
DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
real_irq = dev_priv->irq_map[irq];
|
||||
|
||||
if (real_irq < 0) {
|
||||
DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
|
||||
__FUNCTION__, irq);
|
||||
DRM_ERROR("Video IRQ %d not available on this hardware.\n",
|
||||
irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +260,7 @@ void via_driver_irq_preinstall(struct drm_device * dev)
|
|||
drm_via_irq_t *cur_irq;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
|
||||
DRM_DEBUG("dev_priv: %p\n", dev_priv);
|
||||
if (dev_priv) {
|
||||
cur_irq = dev_priv->via_irqs;
|
||||
|
||||
|
|
@ -301,23 +302,24 @@ void via_driver_irq_preinstall(struct drm_device * dev)
|
|||
}
|
||||
}
|
||||
|
||||
void via_driver_irq_postinstall(struct drm_device * dev)
|
||||
int via_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
u32 status;
|
||||
|
||||
DRM_DEBUG("via_driver_irq_postinstall\n");
|
||||
if (dev_priv) {
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
|
||||
| dev_priv->irq_enable_mask);
|
||||
if (!dev_priv)
|
||||
return -EINVAL;
|
||||
|
||||
/* Some magic, oh for some data sheets ! */
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
|
||||
| dev_priv->irq_enable_mask);
|
||||
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
|
||||
/* Some magic, oh for some data sheets ! */
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void via_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
|
@ -325,7 +327,7 @@ void via_driver_irq_uninstall(struct drm_device * dev)
|
|||
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
u32 status;
|
||||
|
||||
DRM_DEBUG("driver_irq_uninstall)\n");
|
||||
DRM_DEBUG("\n");
|
||||
if (dev_priv) {
|
||||
|
||||
/* Some more magic, oh for some data sheets ! */
|
||||
|
|
@ -352,7 +354,7 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
return -EINVAL;
|
||||
|
||||
if (irqwait->request.irq >= dev_priv->num_irqs) {
|
||||
DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
|
||||
DRM_ERROR("Trying to wait on unknown irq %d\n",
|
||||
irqwait->request.irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -371,8 +373,7 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
}
|
||||
|
||||
if (irqwait->request.type & VIA_IRQ_SIGNAL) {
|
||||
DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
|
||||
__FUNCTION__);
|
||||
DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
|
|||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev_priv->sarea = drm_getsarea(dev);
|
||||
if (!dev_priv->sarea) {
|
||||
|
|
@ -95,7 +95,7 @@ int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
{
|
||||
drm_via_init_t *init = data;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
switch (init->func) {
|
||||
case VIA_INIT_MAP:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ void via_init_futex(drm_via_private_t * dev_priv)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
|
||||
DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
|
||||
|
|
@ -73,7 +73,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_
|
|||
drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (fx->lock > VIA_NR_XVMC_LOCKS)
|
||||
return -EFAULT;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue