summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-01-25 15:27:53 +1000
committerDave Airlie <airlied@redhat.com>2008-01-25 15:27:53 +1000
commite7a41d7f5be49241480a20eb733262712e0f8dcb (patch)
tree801c7eadf769db981dfb8a900a24ef48542958a6
parentfb9ea12438de95a6ac085879e079055eaea3daf8 (diff)
parentbfdddd218ec3e7ce3f8e765b93af35661a7bf0fd (diff)
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
-rw-r--r--libdrm/xf86drm.c6
-rw-r--r--libdrm/xf86mm.h2
-rw-r--r--linux-core/ati_pcigart.c6
-rw-r--r--linux-core/drmP.h91
-rw-r--r--linux-core/drm_agpsupport.c16
-rw-r--r--linux-core/drm_bo.c270
-rw-r--r--linux-core/drm_bo_move.c18
-rw-r--r--linux-core/drm_compat.c2
-rw-r--r--linux-core/drm_drv.c5
-rw-r--r--linux-core/drm_irq.c354
-rw-r--r--linux-core/drm_object.c2
-rw-r--r--linux-core/drm_objects.h127
-rw-r--r--linux-core/drm_scatter.c10
-rw-r--r--linux-core/drm_ttm.c139
-rw-r--r--linux-core/drm_vm.c8
-rw-r--r--linux-core/i810_dma.c22
-rw-r--r--linux-core/i810_drv.h2
-rw-r--r--linux-core/i915_buffer.c26
-rw-r--r--linux-core/i915_compat.c20
-rw-r--r--linux-core/i915_drv.c14
-rw-r--r--linux-core/i915_ioc32.c63
-rw-r--r--linux-core/mach64_drv.c6
-rw-r--r--linux-core/mga_drv.c7
-rw-r--r--linux-core/nouveau_buffer.c15
-rw-r--r--linux-core/nouveau_sgdma.c33
-rw-r--r--linux-core/r128_drv.c7
-rw-r--r--linux-core/radeon_buffer.c6
-rw-r--r--linux-core/radeon_drv.c10
-rw-r--r--linux-core/radeon_ms_drv.c5
-rw-r--r--linux-core/sis_mm.c4
-rw-r--r--linux-core/via_buffer.c2
-rw-r--r--linux-core/via_mm.c4
-rw-r--r--shared-core/drm.h76
-rw-r--r--shared-core/drm_pciids.txt98
-rw-r--r--shared-core/i915_dma.c152
-rw-r--r--shared-core/i915_drm.h10
-rw-r--r--shared-core/i915_drv.h72
-rw-r--r--shared-core/i915_irq.c326
-rw-r--r--shared-core/i915_mem.c8
-rw-r--r--shared-core/mach64_dma.c167
-rw-r--r--shared-core/mach64_drv.h210
-rw-r--r--shared-core/mach64_irq.c88
-rw-r--r--shared-core/mach64_state.c43
-rw-r--r--shared-core/mga_dma.c4
-rw-r--r--shared-core/mga_drv.h21
-rw-r--r--shared-core/mga_irq.c69
-rw-r--r--shared-core/mga_state.c14
-rw-r--r--shared-core/nouveau_drv.h2
-rw-r--r--shared-core/nouveau_irq.c4
-rw-r--r--shared-core/nouveau_mem.c2
-rw-r--r--shared-core/nouveau_reg.h3
-rw-r--r--shared-core/nouveau_state.c95
-rw-r--r--shared-core/nv04_graph.c2
-rw-r--r--shared-core/nv04_mc.c13
-rw-r--r--shared-core/nv20_graph.c18
-rw-r--r--shared-core/nv50_fifo.c92
-rw-r--r--shared-core/nv50_graph.c102
-rw-r--r--shared-core/nv50_instmem.c4
-rw-r--r--shared-core/r128_cce.c4
-rw-r--r--shared-core/r128_drv.h12
-rw-r--r--shared-core/r128_irq.c55
-rw-r--r--shared-core/r128_state.c43
-rw-r--r--shared-core/r300_cmdbuf.c39
-rw-r--r--shared-core/radeon_cp.c117
-rw-r--r--shared-core/radeon_drv.h48
-rw-r--r--shared-core/radeon_irq.c175
-rw-r--r--shared-core/radeon_mem.c6
-rw-r--r--shared-core/radeon_ms.h2
-rw-r--r--shared-core/radeon_ms_bo.c6
-rw-r--r--shared-core/radeon_ms_drm.c2
-rw-r--r--shared-core/radeon_state.c33
-rw-r--r--shared-core/via_dma.c20
-rw-r--r--shared-core/via_drv.c8
-rw-r--r--shared-core/via_drv.h9
-rw-r--r--shared-core/via_irq.c89
-rw-r--r--shared-core/via_map.c4
-rw-r--r--shared-core/via_video.c4
77 files changed, 2410 insertions, 1263 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 3cc54f12..39a849c6 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -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;
diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h
index d3df8497..c80288a7 100644
--- a/libdrm/xf86mm.h
+++ b/libdrm/xf86mm.h
@@ -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;
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 5fafbb93..c669067b 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -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);
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 2f0791c0..1c815c5f 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -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);
diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c
index 0b321afd..adcb93a5 100644
--- a/linux-core/drm_agpsupport.c
+++ b/linux-core/drm_agpsupport.c
@@ -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;
}
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 55f5d08a..6b3d4e14 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -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;
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index 97946b3c..db433d63 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -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;
}
diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c
index 67c8c998..a745a7d9 100644
--- a/linux-core/drm_compat.c
+++ b/linux-core/drm_compat.c
@@ -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;
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 4ecea67f..ab047ca3 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -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,
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index 314c2329..367d2dd8 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -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);
@@ -213,6 +289,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.
*
* \param inode device inode.
@@ -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);
-
- 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);
+ vbl_sigs = &dev->vbl_sigs[crtc];
+ vbl_seq = drm_vblank_count(dev, crtc);
- list_del(&vbl_sig->head);
+ 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);
- drm_free(vbl_sig, sizeof(*vbl_sig),
- DRM_MEM_DRIVER);
+ list_del(&vbl_sig->head);
- 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.
diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c
index 16ccdbcb..2994b716 100644
--- a/linux-core/drm_object.c
+++ b/linux-core/drm_object.c
@@ -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;
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index 394a2721..53fad3af 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -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);
/*
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
index 920b11c8..77b9f95d 100644
--- a/linux-core/drm_scatter.c
+++ b/linux-core/drm_scatter.c
@@ -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);
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index 3540571f..a9d87338 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -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);
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index f439fa21..15e1c0f5 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -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;
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 64c7c0db..f2bf5d9d 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -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);
diff --git a/linux-core/i810_drv.h b/linux-core/i810_drv.h
index 86278e3d..f5c175fe 100644
--- a/linux-core/i810_drv.h
+++ b/linux-core/i810_drv.h
@@ -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; \
diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c
index c455a515..54aa75ad 100644
--- a/linux-core/i915_buffer.c
+++ b/linux-core/i915_buffer.c
@@ -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();
}
diff --git a/linux-core/i915_compat.c b/linux-core/i915_compat.c
index 58fb8418..f3e0a081 100644
--- a/linux-core/i915_compat.c
+++ b/linux-core/i915_compat.c
@@ -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)
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 598039dc..629a39be 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -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,
diff --git a/linux-core/i915_ioc32.c b/linux-core/i915_ioc32.c
index 11dee035..0b8fff19 100644
--- a/linux-core/i915_ioc32.c
+++ b/linux-core/i915_ioc32.c
@@ -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
};
/**
diff --git a/linux-core/mach64_drv.c b/linux-core/mach64_drv.c
index 9709934d..16bc9ff3 100644
--- a/linux-core/mach64_drv.c
+++ b/linux-core/mach64_drv.c
@@ -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,
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index bab90aa5..14a0be45 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -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,
diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c
index 9b252a05..a652bb1d 100644
--- a/linux-core/nouveau_buffer.c
+++ b/linux-core/nouveau_buffer.c
@@ -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
};
diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c
index f3bf5341..cc4d5a92 100644
--- a/linux-core/nouveau_sgdma.c
+++ b/linux-core/nouveau_sgdma.c
@@ -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;
}
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c
index ef4a5cbd..7b6159b9 100644
--- a/linux-core/r128_drv.c
+++ b/linux-core/r128_drv.c
@@ -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,
diff --git a/linux-core/radeon_buffer.c b/linux-core/radeon_buffer.c
index 8e2b20b1..5dff1898 100644
--- a/linux-core/radeon_buffer.c
+++ b/linux-core/radeon_buffer.c
@@ -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;
diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c
index 2e491304..355e4c22 100644
--- a/linux-core/radeon_drv.c
+++ b/linux-core/radeon_drv.c
@@ -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,
diff --git a/linux-core/radeon_ms_drv.c b/linux-core/radeon_ms_drv.c
index 4b52a7d7..d7b0eecc 100644
--- a/linux-core/radeon_ms_drv.c
+++ b/linux-core/radeon_ms_drv.c
@@ -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,
diff --git a/linux-core/sis_mm.c b/linux-core/sis_mm.c
index 5110d6e5..6782731d 100644
--- a/linux-core/sis_mm.c
+++ b/linux-core/sis_mm.c
@@ -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;
}
diff --git a/linux-core/via_buffer.c b/linux-core/via_buffer.c
index ea755247..532fae6a 100644
--- a/linux-core/via_buffer.c
+++ b/linux-core/via_buffer.c
@@ -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:
diff --git a/linux-core/via_mm.c b/linux-core/via_mm.c
index 270eac15..3f75af38 100644
--- a/linux-core/via_mm.c
+++ b/linux-core/via_mm.c
@@ -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;
diff --git a/shared-core/drm.h b/shared-core/drm.h
index f8d44048..7aea3033 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -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.
*
@@ -662,6 +677,10 @@ struct drm_fence_arg {
#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)
+
/*@}*/
/**
diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt
index a76413d4..7ef34dfd 100644
--- a/shared-core/drm_pciids.txt
+++ b/shared-core/drm_pciids.txt
@@ -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"
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 4c1a07ac..66d1b13d 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -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;
+
+ for (i = 0; i <= num_buffers; i++)
+ if (buffers[i].buffer)
+ if (reloc[2] == buffers[i].buffer->base.hash.key)
+ buf_index = i;
- if (reloc[2] >= num_buffers) {
+ 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;
-
- 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;
+ 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;
- 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;
}
- /* get next relocate buffer handle */
- *reloc_buf_handle = reloc_page[1];
- 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]);
-
- reloc_page_offset = 0;
- reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t);
- reloc_end = reloc_offset + (num_relocs * reloc_stride);
-
- do {
- next_offset = drm_bo_offset_end(reloc_offset, reloc_end);
+ 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;
+ }
- 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;
+ if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) {
+ ret = -EFAULT;
+ goto out;
+ }
- reloc_offset += reloc_stride;
- } while (reloc_offset < next_offset);
+ /* get next relocate buffer handle */
+ *reloc_user_ptr = (uint32_t *)*(unsigned long *)&reloc_buf[2];
- drm_bo_kunmap(&reloc_kmap);
+ reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */
- 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;
- }
+ DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, *reloc_user_ptr);
- reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
- reloc_page_offset = reloc_offset & ~PAGE_MASK;
- }
+ 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;
+ }
- } 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);
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index c5819953..d48d7665 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -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;
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 45b7786a..49e23ac3 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -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)
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index ac5361f2..9b391b75 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -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)
@@ -61,6 +61,44 @@ i915_get_pipe(struct drm_device *dev, int plane)
}
/**
+ * 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.
*
* This function must be called with the drawable spinlock held.
@@ -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);
}
-void i915_enable_interrupt (struct drm_device *dev)
+int i915_enable_vblank(struct drm_device *dev, int plane)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- struct drm_output *o;
+ int pipe = i915_get_pipe(dev, plane);
- dev_priv->irq_enable_reg = USER_INT_FLAG;
-
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+ switch (pipe) {
+ case 0:
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+ 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 (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)
diff --git a/shared-core/i915_mem.c b/shared-core/i915_mem.c
index 4c7ced24..f24547c7 100644
--- a/shared-core/i915_mem.c
+++ b/shared-core/i915_mem.c
@@ -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;
}
diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c
index 411b98d5..339234fa 100644
--- a/shared-core/mach64_dma.c
+++ b/shared-core/mach64_dma.c
@@ -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;
}
}
diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h
index 1768a2a4..fb8a7724 100644
--- a/shared-core/mach64_drv.h
+++ b/shared-core/mach64_drv.h
@@ -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 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 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 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( "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 \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__ */
diff --git a/shared-core/mach64_irq.c b/shared-core/mach64_irq.c
index 4122dd91..2d522a6c 100644
--- a/shared-core/mach64_irq.c
+++ b/shared-core/mach64_irq.c
@@ -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)));
+ const drm_mach64_private_t *const dev_priv = dev->dev_private;
+
+ if (crtc != 0) {
+ return 0;
+ }
+
+ return atomic_read(&dev_priv->vbl_received);
+}
- *sequence = cur_vblank;
+int mach64_enable_vblank(struct drm_device * dev, int crtc)
+{
+ 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 ret;
+ return 0;
}
-/* 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;
+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));
diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c
index 88ff4843..c82f38bb 100644
--- a/shared-core/mach64_state.c
+++ b/shared-core/mach64_state.c
@@ -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;
}
diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c
index 67236b2d..d56f4d7a 100644
--- a/shared-core/mga_dma.c
+++ b/shared-core/mga_dma.c
@@ -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);
diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h
index 0c7fab5b..bf3be808 100644
--- a/shared-core/mga_drv.h
+++ b/shared-core/mga_drv.h
@@ -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 ) - \
diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c
index 0f83577f..4fe86322 100644
--- a/shared-core/mga_irq.c
+++ b/shared-core/mga_irq.c
@@ -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...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
- - *sequence) <= (1 << 23)));
+ if (crtc != 0) {
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ return 0;
+ }
- *sequence = cur_vblank;
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ return 0;
+}
- return ret;
+
+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.
+ */
+ /* 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)
diff --git a/shared-core/mga_state.c b/shared-core/mga_state.c
index d9cc9d7e..2da108be 100644
--- a/shared-core/mga_state.c
+++ b/shared-core/mga_state.c
@@ -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;
}
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 85a0d0b5..4184aa5b 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -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 */
diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c
index 500fda2f..bceb81ab 100644
--- a/shared-core/nouveau_irq.c
+++ b/shared-core/nouveau_irq.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
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index 5259ea27..f4e641b9 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -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;
}
diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h
index 7ac02f4a..a2506146 100644
--- a/shared-core/nouveau_reg.h
+++ b/shared-core/nouveau_reg.h
@@ -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
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index 16c86494..7086a0ab 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -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;
diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c
index 81a6d5c8..6caae257 100644
--- a/shared-core/nv04_graph.c
+++ b/shared-core/nv04_graph.c
@@ -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);
diff --git a/shared-core/nv04_mc.c b/shared-core/nv04_mc.c
index 24c1f7b3..766f3a33 100644
--- a/shared-core/nv04_mc.c
+++ b/shared-core/nv04_mc.c
@@ -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;
}
diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c
index 81501ed7..37a147b5 100644
--- a/shared-core/nv20_graph.c
+++ b/shared-core/nv20_graph.c
@@ -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);
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
index c5cde913..edf4edbf 100644
--- a/shared-core/nv50_fifo.c
+++ b/shared-core/nv50_fifo.c
@@ -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;
}
- nv50_fifo_init_context_table(dev);
+ 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;
diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c
index 5814abd4..503f45dd 100644
--- a/shared-core/nv50_graph.c
+++ b/shared-core/nv50_graph.c
@@ -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);
diff --git a/shared-core/nv50_instmem.c b/shared-core/nv50_instmem.c
index c80574a9..9687ecbb 100644
--- a/shared-core/nv50_instmem.c
+++ b/shared-core/nv50_instmem.c
@@ -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.
diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c
index 8ce128bd..204ea37d 100644
--- a/shared-core/r128_cce.c
+++ b/shared-core/r128_cce.c
@@ -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;
}
diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h
index b0558389..ab8b6297 100644
--- a/shared-core/r128_drv.h
+++ b/shared-core/r128_drv.h
@@ -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(); \
diff --git a/shared-core/r128_irq.c b/shared-core/r128_irq.c
index c76fdca7..5b95bd89 100644
--- a/shared-core/r128_irq.c
+++ b/shared-core/r128_irq.c
@@ -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...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
- - *sequence) <= (1 << 23)));
+ if (crtc != 0) {
+ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
+ return -EINVAL;
+ }
- *sequence = cur_vblank;
+ 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);
- return ret;
+ /*
+ * 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);
+ */
}
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)
diff --git a/shared-core/r128_state.c b/shared-core/r128_state.c
index b7f483ca..51a9afce 100644
--- a/shared-core/r128_state.c
+++ b/shared-core/r128_state.c
@@ -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;
}
diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c
index 6ab907c6..a26a71d5 100644
--- a/shared-core/r300_cmdbuf.c
+++ b/shared-core/r300_cmdbuf.c
@@ -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)
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index c2863346..f0e55105 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -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:
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index 37b9c43f..63877008 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -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(); \
diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c
index 544e3a0f..3f6ace88 100644
--- a/shared-core/radeon_irq.c
+++ b/shared-core/radeon_irq.c
@@ -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;
}
diff --git a/shared-core/radeon_mem.c b/shared-core/radeon_mem.c
index 9947e940..1e582ee0 100644
--- a/shared-core/radeon_mem.c
+++ b/shared-core/radeon_mem.c
@@ -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;
}
diff --git a/shared-core/radeon_ms.h b/shared-core/radeon_ms.h
index a784882b..66533837 100644
--- a/shared-core/radeon_ms.h
+++ b/shared-core/radeon_ms.h
@@ -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);
diff --git a/shared-core/radeon_ms_bo.c b/shared-core/radeon_ms_bo.c
index cedad689..6d9a97c1 100644
--- a/shared-core/radeon_ms_bo.c
+++ b/shared-core/radeon_ms_bo.c
@@ -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:
diff --git a/shared-core/radeon_ms_drm.c b/shared-core/radeon_ms_drm.c
index 91ca4a32..bf76b45d 100644
--- a/shared-core/radeon_ms_drm.c
+++ b/shared-core/radeon_ms_drm.c
@@ -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,
};
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 623576ad..6f2e05b3 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -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;
}
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index ab39f53c..431738a9 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -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;
}
diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c
index 9f099555..a802e4ae 100644
--- a/shared-core/via_drv.c
+++ b/shared-core/via_drv.c
@@ -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,
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index d6da8bd9..8dd4a727 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -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
diff --git a/shared-core/via_irq.c b/shared-core/via_irq.c
index ec3f50bd..b8e652e6 100644
--- a/shared-core/via_irq.c
+++ b/shared-core/via_irq.c
@@ -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);
-
- /* 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)));
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+ return 0;
+}
- *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;
}
diff --git a/shared-core/via_map.c b/shared-core/via_map.c
index b8f61673..11bfa551 100644
--- a/shared-core/via_map.c
+++ b/shared-core/via_map.c
@@ -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:
diff --git a/shared-core/via_video.c b/shared-core/via_video.c
index c15e75b5..6ec04ac1 100644
--- a/shared-core/via_video.c
+++ b/shared-core/via_video.c
@@ -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;