diff options
author | rnoland <rnoland@FreeBSD.org> | 2009-03-07 21:36:57 +0000 |
---|---|---|
committer | rnoland <rnoland@FreeBSD.org> | 2009-03-07 21:36:57 +0000 |
commit | 67b6c21b746eccc2864dcfd479c48ab8722b44b4 (patch) | |
tree | ff4dc0e683815f28195164b5c8c03653531dd2d2 /sys/dev/drm/radeon_state.c | |
parent | 4ab7fdce6336043e51096627dbc9438b5aa88a39 (diff) | |
download | FreeBSD-src-67b6c21b746eccc2864dcfd479c48ab8722b44b4.zip FreeBSD-src-67b6c21b746eccc2864dcfd479c48ab8722b44b4.tar.gz |
Import support for ATI Radeon R600 and R700 series chips.
Tested on an HD3850 (RV670) on loan from Warren Block.
Currently, you need one of the following for this to be useful:
x11-drivers/xf86-video-radeonhd-devel (not tested)
xf86-video-ati from git (EXA works, xv is too fast)
xf86-video-radeonhd from git (EXA works, xv works)
There is no 3d support available from dri just yet.
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/drm/radeon_state.c')
-rw-r--r-- | sys/dev/drm/radeon_state.c | 186 |
1 files changed, 71 insertions, 115 deletions
diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c index d06748d..39dcd61 100644 --- a/sys/dev/drm/radeon_state.c +++ b/sys/dev/drm/radeon_state.c @@ -1,4 +1,3 @@ -/* radeon_state.c -- State support for Radeon -*- linux-c -*- */ /*- * Copyright 2000 VA Linux Systems, Inc., Fremont, California. * All Rights Reserved. @@ -43,7 +42,7 @@ __FBSDID("$FreeBSD$"); static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * dev_priv, struct drm_file *file_priv, - u32 * offset) + u32 *offset) { u64 off = *offset; u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1; @@ -308,9 +307,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * case RADEON_CP_3D_DRAW_INDX_2: case RADEON_3D_CLEAR_HIZ: /* safe but r200 only */ - if ((dev_priv->chip_family < CHIP_R200) || - (dev_priv->chip_family > CHIP_RV280)) { - DRM_ERROR("Invalid 3d packet for non r200-class chip\n"); + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); return -EINVAL; } break; @@ -363,8 +361,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * break; case RADEON_3D_RNDR_GEN_INDX_PRIM: - if (dev_priv->chip_family > CHIP_RS200) { - DRM_ERROR("Invalid 3d packet for non-r100-class chip\n"); + if (dev_priv->microcode_version != UCODE_R100) { + DRM_ERROR("Invalid 3d packet for r200-class chip\n"); return -EINVAL; } if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { @@ -374,10 +372,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * break; case RADEON_CP_INDX_BUFFER: - /* safe but r200 only */ - if ((dev_priv->chip_family < CHIP_R200) || - (dev_priv->chip_family > CHIP_RV280)) { - DRM_ERROR("Invalid 3d packet for non-r200-class chip\n"); + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); return -EINVAL; } if ((cmd[1] & 0x8000ffff) != 0x80000810) { @@ -796,7 +792,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, ADVANCE_RING(); } -static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) +static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv) { /* Collapse various things into a wait flag -- trying to * guess if userspase slept -- better just to have them tell us. @@ -870,7 +866,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, dev_priv->stats.clears++; - if (dev_priv->sarea_priv->pfCurrentPage == 1) { + if (sarea_priv->pfCurrentPage == 1) { unsigned int tmp = flags; flags &= ~(RADEON_FRONT | RADEON_BACK); @@ -896,7 +892,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { int x = pbox[i].x1; @@ -973,7 +969,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. * we haven't touched any "normal" state - still need this? */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; if ((dev_priv->flags & RADEON_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) { @@ -1021,7 +1017,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, int tileoffset, nrtilesx, nrtilesy, j; /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ if ((dev_priv->flags & RADEON_HAS_HIERZ) - && (dev_priv->chip_family < CHIP_R200)) { + && !(dev_priv->microcode_version == UCODE_R200)) { /* FIXME : figure this out for r200 (when hierz is enabled). Or maybe r200 actually doesn't need to put the low-res z value into the tile cache like r100, but just needs to clear the hi-level z-buffer? @@ -1050,8 +1046,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, ADVANCE_RING(); tileoffset += depthpixperline >> 6; } - } else if ((dev_priv->chip_family >= CHIP_R200) && - (dev_priv->chip_family <= CHIP_RV280)) { + } else if (dev_priv->microcode_version == UCODE_R200) { /* works for rv250. */ /* find first macro tile (8x2 4x4 z-pixels on rv250) */ tileoffset = @@ -1106,8 +1101,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* TODO don't always clear all hi-level z tiles */ if ((dev_priv->flags & RADEON_HAS_HIERZ) - && ((dev_priv->chip_family >= CHIP_R200) && - (dev_priv->chip_family <= CHIP_RV280)) + && (dev_priv->microcode_version == UCODE_R200) && (flags & RADEON_USE_HIERZ)) /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ /* FIXME : the mask supposedly contains low-res z values. So can't set @@ -1127,9 +1121,8 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, * rendering a quad into just those buffers. Thus, we have to * make sure the 3D engine is configured correctly. */ - else if ((dev_priv->chip_family >= CHIP_R200) && - (dev_priv->chip_family <= CHIP_RV280) && - (flags & (RADEON_DEPTH | RADEON_STENCIL))) { + else if ((dev_priv->microcode_version == UCODE_R200) && + (flags & (RADEON_DEPTH | RADEON_STENCIL))) { int tempPP_CNTL; int tempRE_CNTL; @@ -1223,7 +1216,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { @@ -1294,7 +1287,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, /* Make sure we restore the 3D state next time. */ - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; for (i = 0; i < nbox; i++) { @@ -1337,17 +1330,17 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, * wait on this value before performing the clear ioctl. We * need this because the card's so damned fast... */ - dev_priv->sarea_priv->last_clear++; + sarea_priv->last_clear++; BEGIN_RING(4); - RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear); + RADEON_CLEAR_AGE(sarea_priv->last_clear); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); } -static void radeon_cp_dispatch_swap(struct drm_device * dev) +static void radeon_cp_dispatch_swap(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; @@ -1394,7 +1387,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) /* Make this work even if front & back are flipped: */ OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); - if (dev_priv->sarea_priv->pfCurrentPage == 0) { + if (sarea_priv->pfCurrentPage == 0) { OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->front_pitch_offset); } else { @@ -1414,20 +1407,20 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ - dev_priv->sarea_priv->last_frame++; + sarea_priv->last_frame++; BEGIN_RING(4); - RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); + RADEON_FRAME_AGE(sarea_priv->last_frame); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); } -static void radeon_cp_dispatch_flip(struct drm_device * dev) +static void radeon_cp_dispatch_flip(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle; + struct drm_sarea *sarea = (struct drm_sarea *)dev_priv->sarea->handle; int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; @@ -1548,7 +1541,7 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev, } while (i < nbox); } -static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf) +static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_buf *buf) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; @@ -1557,9 +1550,15 @@ static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * b buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ - BEGIN_RING(2); - RADEON_DISPATCH_AGE(buf_priv->age); - ADVANCE_RING(); + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { + BEGIN_RING(3); + R600_DISPATCH_AGE(buf_priv->age); + ADVANCE_RING(); + } else { + BEGIN_RING(2); + RADEON_DISPATCH_AGE(buf_priv->age); + ADVANCE_RING(); + } buf->pending = 1; buf->used = 0; @@ -1599,7 +1598,7 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev, } } -static void radeon_cp_dispatch_indices(struct drm_device * dev, +static void radeon_cp_dispatch_indices(struct drm_device *dev, struct drm_buf * elt_buf, drm_radeon_tcl_prim_t * prim) { @@ -2099,11 +2098,6 @@ static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_f drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_alloc_t *alloc = data; - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - if (alloc_surface(alloc, dev_priv, file_priv) == -1) return -EINVAL; else @@ -2115,11 +2109,6 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_free_t *memfree = data; - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - if (free_surface(file_priv, dev_priv, memfree->address)) return -EINVAL; else @@ -2153,7 +2142,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * /* Not sure why this isn't set all the time: */ -static int radeon_do_init_pageflip(struct drm_device * dev) +static int radeon_do_init_pageflip(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -2203,6 +2192,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -2213,7 +2203,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; radeon_cp_dispatch_swap(dev); - dev_priv->sarea_priv->ctx_owner = 0; + sarea_priv->ctx_owner = 0; COMMIT_RING(); return 0; @@ -2230,11 +2220,6 @@ 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("called with no initialization\n"); - return -EINVAL; - } - sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", @@ -2289,7 +2274,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file prim.finish = vertex->count; /* unused */ prim.prim = vertex->prim; prim.numverts = vertex->count; - prim.vc_format = dev_priv->sarea_priv->vc_format; + prim.vc_format = sarea_priv->vc_format; radeon_cp_dispatch_vertex(dev, buf, &prim); } @@ -2314,10 +2299,6 @@ 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("called with no initialization\n"); - return -EINVAL; - } sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", @@ -2385,7 +2366,7 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file prim.prim = elts->prim; prim.offset = 0; /* offset from start of dma buffers */ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - prim.vc_format = dev_priv->sarea_priv->vc_format; + prim.vc_format = sarea_priv->vc_format; radeon_cp_dispatch_indices(dev, buf, &prim); if (elts->discard) { @@ -2490,24 +2471,25 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil buf->used = indirect->end; - /* Wait for the 3D stream to idle before the indirect buffer - * containing 2D acceleration commands is processed. - */ - BEGIN_RING(2); - - RADEON_WAIT_UNTIL_3D_IDLE(); - - ADVANCE_RING(); - /* Dispatch the indirect buffer full of commands from the * X server. This is insecure and is thus only available to * privileged clients. */ - radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); - if (indirect->discard) { - radeon_cp_discard_buffer(dev, buf); + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); + else { + /* Wait for the 3D stream to idle before the indirect buffer + * containing 2D acceleration commands is processed. + */ + BEGIN_RING(2); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); } + if (indirect->discard) + radeon_cp_discard_buffer(dev, buf); + COMMIT_RING(); return 0; } @@ -2524,11 +2506,6 @@ 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("called with no initialization\n"); - return -EINVAL; - } - sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("pid=%d index=%d discard=%d\n", @@ -2719,10 +2696,10 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); RING_LOCALS; - if (!sz) - return 0; - if (sz * 4 > cmdbuf->bufsz) - return -EINVAL; + if (!sz) + return 0; + if (sz * 4 > cmdbuf->bufsz) + return -EINVAL; BEGIN_RING(5 + sz); OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); @@ -2867,11 +2844,6 @@ 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("called with no initialization\n"); - return -EINVAL; - } - RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); @@ -2898,7 +2870,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file orig_nbox = cmdbuf->nbox; - if (dev_priv->chip_family >= CHIP_R300) { + if (dev_priv->microcode_version == UCODE_R300) { int temp; temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); @@ -3028,11 +3000,6 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil drm_radeon_getparam_t *param = data; int value; - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); switch (param->param) { @@ -3041,14 +3008,14 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil break; case RADEON_PARAM_LAST_FRAME: dev_priv->stats.last_frame_reads++; - value = GET_SCRATCH(0); + value = GET_SCRATCH(dev_priv, 0); break; case RADEON_PARAM_LAST_DISPATCH: - value = GET_SCRATCH(1); + value = GET_SCRATCH(dev_priv, 1); break; case RADEON_PARAM_LAST_CLEAR: dev_priv->stats.last_clear_reads++; - value = GET_SCRATCH(2); + value = GET_SCRATCH(dev_priv, 2); break; case RADEON_PARAM_IRQ_NR: value = dev->irq; @@ -3083,9 +3050,11 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil case RADEON_PARAM_SCRATCH_OFFSET: if (!dev_priv->writeback_works) return -EINVAL; - value = RADEON_SCRATCH_REG_OFFSET; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + value = R600_SCRATCH_REG_OFFSET; + else + value = RADEON_SCRATCH_REG_OFFSET; break; - case RADEON_PARAM_CARD_TYPE: if (dev_priv->flags & RADEON_IS_PCIE) value = RADEON_CARD_PCIE; @@ -3104,7 +3073,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil value = dev_priv->num_gb_pipes; break; default: - DRM_DEBUG( "Invalid parameter %d\n", param->param ); + DRM_DEBUG("Invalid parameter %d\n", param->param); return -EINVAL; } @@ -3122,11 +3091,6 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil drm_radeon_setparam_t *sp = data; struct drm_radeon_driver_file_fields *radeon_priv; - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - switch (sp->param) { case RADEON_SETPARAM_FB_LOCATION: radeon_priv = file_priv->driver_priv; @@ -3178,8 +3142,7 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil * * DRM infrastructure takes care of reclaiming dma buffers. */ -void radeon_driver_preclose(struct drm_device *dev, - struct drm_file *file_priv) +void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -3192,14 +3155,7 @@ void radeon_driver_preclose(struct drm_device *dev, void radeon_driver_lastclose(struct drm_device *dev) { - if (dev->dev_private) { - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (dev_priv->sarea_priv && - dev_priv->sarea_priv->pfCurrentPage != 0) - radeon_cp_dispatch_flip(dev); - } - + radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private); radeon_do_release(dev); } @@ -3248,7 +3204,7 @@ struct drm_ioctl_desc radeon_ioctls[] = { DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), |