From 3add9494037e7c88b5e5a476001176784d743a26 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 17 Mar 2008 11:08:03 +1000 Subject: initial r500 RS and FP register and upload code --- shared-core/r300_cmdbuf.c | 70 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index a26a71d5..89a84b7a 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -189,18 +189,14 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_RE_CULL_CNTL, 1); ADD_RANGE(0x42C0, 2); ADD_RANGE(R300_RS_CNTL_0, 2); - ADD_RANGE(R300_RS_INTERP_0, 8); - ADD_RANGE(R300_RS_ROUTE_0, 8); + ADD_RANGE(0x43A4, 2); ADD_RANGE(0x43E8, 1); ADD_RANGE(R300_PFS_CNTL_0, 3); ADD_RANGE(R300_PFS_NODE_0, 4); ADD_RANGE(R300_PFS_TEXI_0, 64); ADD_RANGE(0x46A4, 5); - ADD_RANGE(R300_PFS_INSTR0_0, 64); - ADD_RANGE(R300_PFS_INSTR1_0, 64); - ADD_RANGE(R300_PFS_INSTR2_0, 64); - ADD_RANGE(R300_PFS_INSTR3_0, 64); + ADD_RANGE(R300_RE_FOG_STATE, 1); ADD_RANGE(R300_FOG_COLOR_R, 3); ADD_RANGE(R300_PP_ALPHA_TEST, 2); @@ -241,7 +237,16 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { - ADD_RANGE(0x4074, 16); + ADD_RANGE(R500_RS_IP_0, 16); + ADD_RANGE(R500_RS_INST_0, 16); + } else { + ADD_RANGE(R300_PFS_INSTR0_0, 64); + ADD_RANGE(R300_PFS_INSTR1_0, 64); + ADD_RANGE(R300_PFS_INSTR2_0, 64); + ADD_RANGE(R300_PFS_INSTR3_0, 64); + ADD_RANGE(R300_RS_INTERP_0, 8); + ADD_RANGE(R300_RS_ROUTE_0, 8); + } } @@ -786,6 +791,44 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, return 0; } +/** + * Uploads user-supplied vertex program instructions or parameters onto + * the graphics card. + * Called by r300_do_cp_cmdbuf. + */ +static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int sz; + int addr; + RING_LOCALS; + + sz = header.r500fp.count; + addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + + if (!sz) + return 0; + if (sz * 16 > cmdbuf->bufsz) + return -EINVAL; + + BEGIN_RING(4 + sz * 4); + /* Wait for VAP to come to senses.. */ + /* there is no need to emit it multiple times, (only once before VAP is programmed, + but this optimization is for later */ + OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 4 - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); + + ADVANCE_RING(); + + cmdbuf->buf += sz * 16; + cmdbuf->bufsz -= sz * 16; + + return 0; +} + + /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. @@ -932,6 +975,19 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, } break; + case R300_CMD_R500FP: + if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { + DRM_ERROR("Calling r500 command on r300 card\n"); + ret = -EINVAL; + goto cleanup; + } + DRM_DEBUG("R300_CMD_R500FP\n"); + ret = r300_emit_r500fp(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_emit_r500fp failed\n"); + goto cleanup; + } + break; default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, -- cgit v1.2.3 From a3c808d8feff9dc379f71f971ca20ec3c686b0c0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 19 Mar 2008 16:10:37 +1000 Subject: move some more r300 regs into not allowed on r500 --- shared-core/r300_cmdbuf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 89a84b7a..ccf82d1f 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -192,9 +192,7 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(0x43A4, 2); ADD_RANGE(0x43E8, 1); - ADD_RANGE(R300_PFS_CNTL_0, 3); - ADD_RANGE(R300_PFS_NODE_0, 4); - ADD_RANGE(R300_PFS_TEXI_0, 64); + ADD_RANGE(0x46A4, 5); ADD_RANGE(R300_RE_FOG_STATE, 1); @@ -240,6 +238,9 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R500_RS_IP_0, 16); ADD_RANGE(R500_RS_INST_0, 16); } else { + ADD_RANGE(R300_PFS_CNTL_0, 3); + ADD_RANGE(R300_PFS_NODE_0, 4); + ADD_RANGE(R300_PFS_TEXI_0, 64); ADD_RANGE(R300_PFS_INSTR0_0, 64); ADD_RANGE(R300_PFS_INSTR1_0, 64); ADD_RANGE(R300_PFS_INSTR2_0, 64); -- cgit v1.2.3 From 316979356f05796c5bd5a47dfc29fe48d6874b49 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 20 Mar 2008 14:20:53 +1000 Subject: drm: fixup r500fp submission --- shared-core/r300_cmdbuf.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index ccf82d1f..040a3639 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -332,6 +332,7 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, sz = header.packet0.count; reg = (header.packet0.reghi << 8) | header.packet0.reglo; + DRM_DEBUG("R300_CMD_PACKET0: reg %04x, sz %d\n", reg, sz); if (!sz) return 0; @@ -808,23 +809,21 @@ static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, sz = header.r500fp.count; addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + DRM_DEBUG("r500fp %d %d\n", sz, addr); if (!sz) return 0; - if (sz * 16 > cmdbuf->bufsz) + if (sz * 6 * 4 > cmdbuf->bufsz) return -EINVAL; - BEGIN_RING(4 + sz * 4); - /* Wait for VAP to come to senses.. */ - /* there is no need to emit it multiple times, (only once before VAP is programmed, - but this optimization is for later */ + BEGIN_RING(3 + sz * 6); OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); - OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 4 - 1)); - OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 6 - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * 6); ADVANCE_RING(); - cmdbuf->buf += sz * 16; - cmdbuf->bufsz -= sz * 16; + cmdbuf->buf += sz * 6 * 4; + cmdbuf->bufsz -= sz * 6 * 4; return 0; } @@ -868,7 +867,6 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, switch (header.header.cmd_type) { case R300_CMD_PACKET0: - DRM_DEBUG("R300_CMD_PACKET0\n"); ret = r300_emit_packet0(dev_priv, cmdbuf, header); if (ret) { DRM_ERROR("r300_emit_packet0 failed\n"); -- cgit v1.2.3 From 36e11dd3801734ff5af9f5edb7aa698f0e2c49c2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 21 Mar 2008 16:59:52 +1000 Subject: r500: fragment program upload is also used to upload constants. Limit frag address to 8 bits --- shared-core/r300_cmdbuf.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 040a3639..1ae2e677 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -804,26 +804,38 @@ static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, { int sz; int addr; + int type; + int clamp; + int stride; RING_LOCALS; sz = header.r500fp.count; - addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + /* address is 9 bits 0 - 8, bit 1 of flags is part of address */ + addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; - DRM_DEBUG("r500fp %d %d\n", sz, addr); + type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); + clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); + + addr |= (type << 16); + addr |= (clamp << 17); + + stride = type ? 4 : 6; + + DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type); if (!sz) return 0; - if (sz * 6 * 4 > cmdbuf->bufsz) + if (sz * stride * 4 > cmdbuf->bufsz) return -EINVAL; - BEGIN_RING(3 + sz * 6); + BEGIN_RING(3 + sz * stride); OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); - OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 6 - 1)); - OUT_RING_TABLE((int *)cmdbuf->buf, sz * 6); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride); ADVANCE_RING(); - cmdbuf->buf += sz * 6 * 4; - cmdbuf->bufsz -= sz * 6 * 4; + cmdbuf->buf += sz * stride * 4; + cmdbuf->bufsz -= sz * stride * 4; return 0; } -- cgit v1.2.3 From 1674d2817929fe4ee4e1c4762e89600119dbdc50 Mon Sep 17 00:00:00 2001 From: Oliver McFadden Date: Sat, 29 Mar 2008 17:25:44 +0000 Subject: r300: Correctly translate the value for the R300_CMD_WAIT command. Previously, the R300_CMD_WAIT command would write the passed directly to the hardware. However this is incorrect because the R300_WAIT_* values used are internal interface values that do not map directly to the hardware. The new function I have added translates the R300_WAIT_* values into appropriate values for the hardware before writing the register. Thanks to John Bridgman for pointing this out. :-) --- shared-core/r300_cmdbuf.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 1ae2e677..db5186c8 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -736,6 +736,32 @@ static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) buf->used = 0; } +static void r300_cmd_wait(drm_radeon_private_t * dev_priv, + drm_r300_cmd_header_t header) +{ + RING_LOCALS; + u32 wait_until; + + if (!header.wait.flags) + return; + + wait_until = 0; + + if (header.wait.flags & R300_WAIT_2D) + wait_until |= RADEON_WAIT_2D_IDLE; + if (header.wait.flags & R300_WAIT_3D) + wait_until |= RADEON_WAIT_3D_IDLE; + if (header.wait.flags & R300_WAIT_2D_CLEAN) + wait_until |= RADEON_WAIT_2D_IDLECLEAN; + if (header.wait.flags & R300_WAIT_3D_CLEAN) + wait_until |= RADEON_WAIT_3D_IDLECLEAN; + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(wait_until); + ADVANCE_RING(); +} + static int r300_scratch(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf, drm_r300_cmd_header_t header) @@ -962,19 +988,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, break; case R300_CMD_WAIT: - /* simple enough, we can do it here */ DRM_DEBUG("R300_CMD_WAIT\n"); - if (header.wait.flags == 0) - break; /* nothing to do */ - - { - RING_LOCALS; - - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING((header.wait.flags & 0xf) << 14); - ADVANCE_RING(); - } + r300_cmd_wait(dev_priv, header); break; case R300_CMD_SCRATCH: -- cgit v1.2.3 From 753a4bdf1b554490f7b288c0203050b5114433c3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 30 Mar 2008 07:33:39 +1000 Subject: drm/r300: fix wait interface mixup This interface was defined completely wrong, however userspace has only ever used 4 values from it (0x1, 0x2, 0x3 and 0x6), so fix the interface to do what userspace actually expected but define new defines for new users to use it properly. --- shared-core/r300_cmdbuf.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'shared-core/r300_cmdbuf.c') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index db5186c8..0a789014 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -739,22 +739,37 @@ static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) static void r300_cmd_wait(drm_radeon_private_t * dev_priv, drm_r300_cmd_header_t header) { - RING_LOCALS; u32 wait_until; + RING_LOCALS; if (!header.wait.flags) return; wait_until = 0; - if (header.wait.flags & R300_WAIT_2D) - wait_until |= RADEON_WAIT_2D_IDLE; - if (header.wait.flags & R300_WAIT_3D) - wait_until |= RADEON_WAIT_3D_IDLE; - if (header.wait.flags & R300_WAIT_2D_CLEAN) - wait_until |= RADEON_WAIT_2D_IDLECLEAN; - if (header.wait.flags & R300_WAIT_3D_CLEAN) - wait_until |= RADEON_WAIT_3D_IDLECLEAN; + switch(header.wait.flags) { + case R300_WAIT_2D: + wait_until = RADEON_WAIT_2D_IDLE; + break; + case R300_WAIT_3D: + wait_until = RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_3D: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE; + break; + case R300_NEW_WAIT_2D_2D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + break; + case R300_NEW_WAIT_3D_3D_CLEAN: + wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN: + wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; + wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; + break; + default: + return; + } BEGIN_RING(2); OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); -- cgit v1.2.3