diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 13f5ba4e..b0d5b27a 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -644,6 +644,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); + /* Writeback doesn't seem to work everywhere, test it first */ + DRM_WRITE32( &dev_priv->scratch[1], 0 ); + RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); + + for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { + if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef ) + break; + DRM_UDELAY( 1 ); + } + + if ( tmp < dev_priv->usec_timeout ) { + dev_priv->writeback_works = TRUE; + DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp ); + } else { + dev_priv->writeback_works = FALSE; + DRM_DEBUG( "writeback test failed\n" ); + } + dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE( RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -1168,7 +1186,7 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) start = dev_priv->last_buf; for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { - u32 done_age = DRM_READ32(&dev_priv->scratch[1]); + u32 done_age = GET_SCRATCH( 1 ); DRM_DEBUG("done_age = %d\n",done_age); for ( i = start ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index ae66f12e..15c0d4dd 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -76,6 +76,7 @@ typedef struct drm_radeon_private { drm_radeon_freelist_t *tail; int last_buf; volatile u32 *scratch; + int writeback_works; int usec_timeout; int is_pci; @@ -220,6 +221,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS ); #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define GET_SCRATCH( x ) (dev_priv->writeback_works \ + ? DRM_READ32( &dev_priv->scratch[(x)] ) \ + : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) + #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 9e04cbea..fb821055 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -1855,13 +1855,13 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) value = dev_priv->agp_buffers_offset; break; case RADEON_PARAM_LAST_FRAME: - value = DRM_READ32(&dev_priv->scratch[0]); + value = GET_SCRATCH( 0 ); break; case RADEON_PARAM_LAST_DISPATCH: - value = DRM_READ32(&dev_priv->scratch[1]); + value = GET_SCRATCH( 1 ); break; case RADEON_PARAM_LAST_CLEAR: - value = DRM_READ32(&dev_priv->scratch[2]); + value = GET_SCRATCH( 2 ); break; default: return DRM_ERR(EINVAL); diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c index 13f5ba4e..b0d5b27a 100644 --- a/shared/radeon_cp.c +++ b/shared/radeon_cp.c @@ -644,6 +644,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); + /* Writeback doesn't seem to work everywhere, test it first */ + DRM_WRITE32( &dev_priv->scratch[1], 0 ); + RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); + + for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { + if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef ) + break; + DRM_UDELAY( 1 ); + } + + if ( tmp < dev_priv->usec_timeout ) { + dev_priv->writeback_works = TRUE; + DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp ); + } else { + dev_priv->writeback_works = FALSE; + DRM_DEBUG( "writeback test failed\n" ); + } + dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE( RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -1168,7 +1186,7 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) start = dev_priv->last_buf; for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { - u32 done_age = DRM_READ32(&dev_priv->scratch[1]); + u32 done_age = GET_SCRATCH( 1 ); DRM_DEBUG("done_age = %d\n",done_age); for ( i = start ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index ae66f12e..15c0d4dd 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -76,6 +76,7 @@ typedef struct drm_radeon_private { drm_radeon_freelist_t *tail; int last_buf; volatile u32 *scratch; + int writeback_works; int usec_timeout; int is_pci; @@ -220,6 +221,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS ); #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define GET_SCRATCH( x ) (dev_priv->writeback_works \ + ? DRM_READ32( &dev_priv->scratch[(x)] ) \ + : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) + #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) diff --git a/shared/radeon_state.c b/shared/radeon_state.c index 9e04cbea..fb821055 100644 --- a/shared/radeon_state.c +++ b/shared/radeon_state.c @@ -1855,13 +1855,13 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) value = dev_priv->agp_buffers_offset; break; case RADEON_PARAM_LAST_FRAME: - value = DRM_READ32(&dev_priv->scratch[0]); + value = GET_SCRATCH( 0 ); break; case RADEON_PARAM_LAST_DISPATCH: - value = DRM_READ32(&dev_priv->scratch[1]); + value = GET_SCRATCH( 1 ); break; case RADEON_PARAM_LAST_CLEAR: - value = DRM_READ32(&dev_priv->scratch[2]); + value = GET_SCRATCH( 2 ); break; default: return DRM_ERR(EINVAL);