summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-07-28 15:21:13 +1000
committerDave Airlie <airlied@redhat.com>2008-07-28 15:21:13 +1000
commit38835f9cd2b44cfb6587a52ba1bfe292b958d0e1 (patch)
tree1d2696a56974fdf756bb271f2b1e74b030c378f9 /shared-core
parent5282a505b6fd1f0e2bb772b15daf652f7149f370 (diff)
radeon command submission start
take code from Jerome munge into a TTM IB re-use
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/radeon_cp.c30
-rw-r--r--shared-core/radeon_cs.c181
-rw-r--r--shared-core/radeon_drm.h15
-rw-r--r--shared-core/radeon_drv.h56
-rw-r--r--shared-core/radeon_state.c1
5 files changed, 256 insertions, 27 deletions
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 80951e91..46f4290a 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -658,8 +658,8 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
((dev_priv->gart_vm_start - 1) & 0xffff0000)
| (dev_priv->fb_location >> 16));
- if (dev_priv->mm.ring) {
- ring_start = dev_priv->mm.ring->offset +
+ if (dev_priv->mm.ring.bo) {
+ ring_start = dev_priv->mm.ring.bo->offset +
dev_priv->gart_vm_start;
} else
#if __OS_HAS_AGP
@@ -692,9 +692,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->ring.tail = cur_read_ptr;
- if (dev_priv->mm.ring_read_ptr) {
+ if (dev_priv->mm.ring_read.bo) {
RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
- dev_priv->mm.ring_read_ptr->offset +
+ dev_priv->mm.ring_read.bo->offset +
dev_priv->gart_vm_start);
} else
#if __OS_HAS_AGP
@@ -745,9 +745,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
+ RADEON_SCRATCH_REG_OFFSET);
- if (dev_priv->mm.ring_read_ptr)
+ if (dev_priv->mm.ring_read.bo)
dev_priv->scratch = ((__volatile__ u32 *)
- dev_priv->mm.ring_read_ptr_map.virtual +
+ dev_priv->mm.ring_read.kmap.virtual +
(RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
else
dev_priv->scratch = ((__volatile__ u32 *)
@@ -772,12 +772,18 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
radeon_do_wait_for_idle(dev_priv);
/* Sync everything up */
+ if (dev_priv->chip_family > CHIP_RV280) {
RADEON_WRITE(RADEON_ISYNC_CNTL,
(RADEON_ISYNC_ANY2D_IDLE3D |
RADEON_ISYNC_ANY3D_IDLE2D |
RADEON_ISYNC_WAIT_IDLEGUI |
RADEON_ISYNC_CPSCRATCH_IDLEGUI));
-
+ } else {
+ RADEON_WRITE(RADEON_ISYNC_CNTL,
+ (RADEON_ISYNC_ANY2D_IDLE3D |
+ RADEON_ISYNC_ANY3D_IDLE2D |
+ RADEON_ISYNC_WAIT_IDLEGUI));
+ }
}
static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
@@ -785,8 +791,8 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
u32 tmp;
void *ring_read_ptr;
- if (dev_priv->mm.ring_read_ptr)
- ring_read_ptr = dev_priv->mm.ring_read_ptr_map.virtual;
+ if (dev_priv->mm.ring_read.bo)
+ ring_read_ptr = dev_priv->mm.ring_read.kmap.virtual;
else
ring_read_ptr = dev_priv->ring_rptr->handle;
@@ -2282,8 +2288,8 @@ int radeon_modeset_cp_init(struct drm_device *dev)
dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE;
dev_priv->cp_mode = RADEON_CSQ_PRIBM_INDBM;
- dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual;
- dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual +
+ dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual;
+ dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual +
dev_priv->ring.size / sizeof(u32);
dev_priv->ring.size_l2qw = drm_order(dev_priv->ring.size / 8);
dev_priv->ring.rptr_update = 4096;
@@ -2297,7 +2303,7 @@ int radeon_modeset_cp_init(struct drm_device *dev)
radeon_cp_load_microcode(dev_priv);
- DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring->offset, dev_priv->mm.ring_read_ptr->offset);
+ DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset);
radeon_cp_init_ring_buffer(dev, dev_priv);
diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c
new file mode 100644
index 00000000..61fef79d
--- /dev/null
+++ b/shared-core/radeon_cs.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2008 Jerome Glisse.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
+{
+ struct drm_radeon_private *radeon = dev->dev_private;
+ struct drm_radeon_cs *cs = data;
+ uint32_t *packets = NULL;
+ uint32_t cs_id;
+ void *ib = NULL;
+ long size;
+ int r;
+
+ /* set command stream id to 0 which is fake id */
+ cs_id = 0;
+ DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
+
+ if (radeon == NULL) {
+ DRM_ERROR("called with no initialization\n");
+ return -EINVAL;
+ }
+ if (!cs->dwords) {
+ return 0;
+ }
+ /* limit cs to 64K ib */
+ if (cs->dwords > (16 * 1024)) {
+ return -EINVAL;
+ }
+ /* copy cs from userspace maybe we should copy into ib to save
+ * one copy but ib will be mapped wc so not good for cmd checking
+ * somethings worth testing i guess (Jerome)
+ */
+ size = cs->dwords * sizeof(uint32_t);
+ packets = drm_alloc(size, DRM_MEM_DRIVER);
+ if (packets == NULL) {
+ return -ENOMEM;
+ }
+ if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) {
+ r = -EFAULT;
+ goto out;
+ }
+ /* get ib */
+ r = radeon->cs.ib_get(dev, &ib, cs->dwords);
+ if (r) {
+ goto out;
+ }
+
+ /* now parse command stream */
+ r = radeon->cs.parse(dev, ib, packets, cs->dwords);
+ if (r) {
+ goto out;
+ }
+
+ /* emit cs id sequence */
+ radeon->cs.id_emit(dev, &cs_id);
+ DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t));
+out:
+ radeon->cs.ib_free(dev, ib, cs->dwords);
+ drm_free(packets, size, DRM_MEM_DRIVER);
+ return r;
+}
+
+int radeon_cs_parse(struct drm_device *dev, void *ib,
+ uint32_t *packets, uint32_t dwords)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ volatile int rb;
+
+ /* copy the packet into the IB */
+ memcpy(ib, packets, dwords * sizeof(uint32_t));
+
+ /* read back last byte to flush WC buffers */
+ rb = readl((ib + (dwords-1) * sizeof(uint32_t)));
+
+ return 0;
+}
+
+uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon)
+{
+ /* FIXME: protect with a spinlock */
+ /* FIXME: check if wrap affect last reported wrap & sequence */
+ radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF;
+ if (!radeon->cs.id_scnt) {
+ /* increment wrap counter */
+ radeon->cs.id_wcnt += 0x01000000;
+ /* valid sequence counter start at 1 */
+ radeon->cs.id_scnt = 1;
+ }
+ return (radeon->cs.id_scnt | radeon->cs.id_wcnt);
+}
+
+void r100_cs_id_emit(struct drm_device *dev, uint32_t *id)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ /* ISYNC_CNTL should have CPSCRACTH bit set */
+ *id = radeon_cs_id_get(dev_priv);
+ /* emit id in SCRATCH4 (not used yet in old drm) */
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0));
+ OUT_RING(*id);
+ ADVANCE_RING();
+}
+
+void r300_cs_id_emit(struct drm_device *dev, uint32_t *id)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+ /* ISYNC_CNTL should not have CPSCRACTH bit set */
+ *id = radeon_cs_id_get(dev_priv);
+ /* emit id in SCRATCH6 */
+ BEGIN_RING(6);
+ OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0));
+ OUT_RING(6);
+ OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0));
+ OUT_RING(*id);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_DC_FINISH);
+ ADVANCE_RING();
+}
+
+uint32_t r100_cs_id_last_get(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ return RADEON_READ(RADEON_SCRATCH_REG4);
+}
+
+uint32_t r300_cs_id_last_get(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ return RADEON_READ(RADEON_SCRATCH_REG6);
+}
+
+int radeon_cs_init(struct drm_device *dev)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ if (dev_priv->chip_family < CHIP_RV280) {
+ dev_priv->cs.id_emit = r100_cs_id_emit;
+ dev_priv->cs.id_last_get = r100_cs_id_last_get;
+ } else if (dev_priv->chip_family < CHIP_R600) {
+ dev_priv->cs.id_emit = r300_cs_id_emit;
+ dev_priv->cs.id_last_get = r300_cs_id_last_get;
+ }
+
+ dev_priv->cs.parse = radeon_cs_parse;
+ /* ib get depends on memory manager or not so memory manager */
+ return 0;
+}
diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h
index 7fcf9305..c20de561 100644
--- a/shared-core/radeon_drm.h
+++ b/shared-core/radeon_drm.h
@@ -506,6 +506,7 @@ typedef struct {
#define DRM_RADEON_GEM_SET_DOMAIN 0x23
#define DRM_RADEON_GEM_INDIRECT 0x24 // temporary for X server
+#define DRM_RADEON_CS 0x25
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -545,6 +546,7 @@ typedef struct {
#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)
#define DRM_IOCTL_RADEON_GEM_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INDIRECT, struct drm_radeon_gem_indirect)
+#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
typedef struct drm_radeon_init {
@@ -861,4 +863,17 @@ struct drm_radeon_gem_indirect {
uint32_t used;
};
+/* New interface which obsolete all previous interface.
+ */
+
+
+struct drm_radeon_cs {
+// uint32_t __user *packets;
+ uint32_t dwords;
+ uint32_t cs_id;
+ uint64_t packets;
+
+};
+
+
#endif
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index b8f49404..c431fe4a 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -195,11 +195,11 @@ enum radeon_mac_model {
#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
- (dev_priv->mm.ring_read_ptr ? readl(dev_priv->mm.ring_read_ptr_map.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \
+ (dev_priv->mm.ring_read.bo ? readl(dev_priv->mm.ring_read.kmap.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \
RADEON_READ(RADEON_CP_RB_RPTR))
-#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read_ptr ? \
- writel((val), dev_priv->mm.ring_read_ptr_map.virtual) : \
+#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read.bo ? \
+ writel((val), dev_priv->mm.ring_read.kmap.virtual) : \
DRM_WRITE32((dev_priv)->ring_rptr, 0, (val)))
typedef struct drm_radeon_freelist {
@@ -261,6 +261,11 @@ struct radeon_virt_surface {
struct drm_file *file_priv;
};
+struct radeon_mm_obj {
+ struct drm_buffer_object *bo;
+ struct drm_bo_kmap_obj kmap;
+};
+
struct radeon_mm_info {
uint64_t vram_offset; // Offset into GPU space
uint64_t vram_size;
@@ -268,15 +273,10 @@ struct radeon_mm_info {
uint64_t gart_start;
uint64_t gart_size;
-
- struct drm_buffer_object *pcie_table;
- struct drm_bo_kmap_obj pcie_table_map;
-
- struct drm_buffer_object *ring;
- struct drm_bo_kmap_obj ring_map;
-
- struct drm_buffer_object *ring_read_ptr;
- struct drm_bo_kmap_obj ring_read_ptr_map;
+
+ struct radeon_mm_obj pcie_table;
+ struct radeon_mm_obj ring;
+ struct radeon_mm_obj ring_read;
};
#include "radeon_mode.h"
@@ -286,6 +286,25 @@ struct drm_radeon_master_private {
drm_radeon_sarea_t *sarea_priv;
};
+/* command submission struct */
+struct drm_radeon_cs_priv {
+ uint32_t id_wcnt;
+ uint32_t id_scnt;
+ uint32_t id_last_wcnt;
+ uint32_t id_last_scnt;
+
+ int (*parse)(struct drm_device *dev, void *ib,
+ uint32_t *packets, uint32_t dwords);
+ void (*id_emit)(struct drm_device *dev, uint32_t *id);
+ uint32_t (*id_last_get)(struct drm_device *dev);
+ /* this ib handling callback are for hidding memory manager drm
+ * from memory manager less drm, free have to emit ib discard
+ * sequence into the ring */
+ int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords);
+ uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib);
+ void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords);
+};
+
typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
@@ -392,7 +411,11 @@ typedef struct drm_radeon_private {
u32 ram_width;
enum radeon_pll_errata pll_errata;
-
+
+ struct radeon_mm_obj **ib_objs;
+ /* ib bitmap */
+ uint64_t ib_alloc_bitmap; // TO DO replace with a real bitmap
+ struct drm_radeon_cs_priv cs;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@@ -669,14 +692,15 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_SCRATCH_REG3 0x15ec
#define RADEON_SCRATCH_REG4 0x15f0
#define RADEON_SCRATCH_REG5 0x15f4
+#define RADEON_SCRATCH_REG6 0x15f8
#define RADEON_SCRATCH_UMSK 0x0770
#define RADEON_SCRATCH_ADDR 0x0774
#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x))
#define GET_SCRATCH( x ) (dev_priv->writeback_works ? \
- (dev_priv->mm.ring_read_ptr ? \
- readl(dev_priv->mm.ring_read_ptr_map.virtual + RADEON_SCRATCHOFF(0)) : \
+ (dev_priv->mm.ring_read.bo ? \
+ readl(dev_priv->mm.ring_read.kmap.virtual + RADEON_SCRATCHOFF(0)) : \
DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \
RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x)))
@@ -1593,4 +1617,6 @@ extern void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on);
extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);
extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);
extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master);
+extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
+extern int radeon_cs_init(struct drm_device *dev);
#endif /* __RADEON_DRV_H__ */
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 6de4b135..d56dac19 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -3279,6 +3279,7 @@ struct drm_ioctl_desc radeon_ioctls[] = {
DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_INDIRECT, radeon_gem_indirect_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
};
int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);