diff --git a/linux/mach64_dma.c b/linux/mach64_dma.c index 8cd4e04a..8fa138b8 100644 --- a/linux/mach64_dma.c +++ b/linux/mach64_dma.c @@ -436,18 +436,18 @@ static int mach64_bm_dma_test( drm_device_t *dev ) /* fill up a buffer with sets of 3 consecutive writes starting with VERTEX_1_S */ count = 0; - data[count++] = cpu_to_le32(0x00020190); /* 1_90 = VERTEX_1_S */ + data[count++] = cpu_to_le32(DMAREG(MACH64_VERTEX_1_S) | (2 << 16)); data[count++] = expected[0] = 0x11111111; data[count++] = expected[1] = 0x22222222; data[count++] = expected[2] = 0x33333333; while (count < 1020) { - data[count++] = cpu_to_le32(0x00020190); + data[count++] = cpu_to_le32(DMAREG(MACH64_VERTEX_1_S) | (2 << 16)); data[count++] = 0x11111111; data[count++] = 0x22222222; data[count++] = 0x33333333; } - data[count++] = cpu_to_le32(0x0000006d); /* SRC_CNTL */ + data[count++] = cpu_to_le32(DMAREG(MACH64_SRC_CNTL) | (0 << 16)); data[count++] = 0; DRM_DEBUG( "Preparing table ...\n" ); diff --git a/linux/mach64_drv.h b/linux/mach64_drv.h index 2ba917a1..e1b3fa60 100644 --- a/linux/mach64_drv.h +++ b/linux/mach64_drv.h @@ -742,4 +742,76 @@ do { \ mach64_dma_start( dev_priv ); \ } while(0) +#define DMAADVANCEHOSTDATA( dev_priv ) \ +do { \ + struct list_head *ptr; \ + drm_mach64_freelist_t *entry; \ + RING_LOCALS; \ + \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \ + } \ + \ + if (list_empty(&dev_priv->placeholders)) { \ + DRM_ERROR( "%s: empty placeholder list in DMAADVANCE()\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); \ + \ + ADD_HOSTDATA_BUF_TO_RING( dev_priv, entry ); \ +} while (0) + +#define ADD_HOSTDATA_BUF_TO_RING( dev_priv, entry ) \ +do { \ + int bytes, pages, remainder; \ + drm_buf_t *buf = entry->buf; \ + u32 address, page; \ + int i; \ + \ + bytes = buf->used - MACH64_HOSTDATA_BLIT_OFFSET; \ + pages = (bytes + DMA_CHUNKSIZE - 1) / DMA_CHUNKSIZE; \ + address = GETBUFADDR( buf ); \ + \ + BEGIN_RING( 4 + pages * 4 ); \ + \ + OUT_RING( APERTURE_OFFSET + MACH64_BM_ADDR ); \ + OUT_RING( address ); \ + OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | DMA_HOLD_OFFSET ); \ + OUT_RING( 0 ); \ + \ + address += MACH64_HOSTDATA_BLIT_OFFSET; \ + \ + for ( i = 0 ; i < pages-1 ; i++ ) { \ + page = address + i * DMA_CHUNKSIZE; \ + OUT_RING( APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ + OUT_RING( page ); \ + OUT_RING( DMA_CHUNKSIZE | DMA_HOLD_OFFSET ); \ + OUT_RING( 0 ); \ + } \ + \ + /* generate the final descriptor for any remaining commands in this buffer */ \ + page = address + i * DMA_CHUNKSIZE; \ + remainder = bytes - i * DMA_CHUNKSIZE; \ + \ + /* Save dword offset of last descriptor for this buffer. \ + * This is needed to check for completion of the buffer in freelist_get \ + */ \ + entry->ring_ofs = RING_WRITE_OFS; \ + \ + OUT_RING( APERTURE_OFFSET + MACH64_BM_HOSTDATA ); \ + OUT_RING( page ); \ + OUT_RING( remainder | DMA_HOLD_OFFSET ); \ + OUT_RING( 0 ); \ + \ + ADVANCE_RING(); \ + mach64_dma_start( dev_priv ); \ +} while(0) + #endif /* __MACH64_DRV_H__ */ diff --git a/linux/mach64_state.c b/linux/mach64_state.c index 7900416e..e936ec14 100644 --- a/linux/mach64_state.c +++ b/linux/mach64_state.c @@ -467,13 +467,15 @@ static int mach64_dma_dispatch_blit( drm_device_t *dev, p = GETBUFPTR( buf ); dwords = (blit->width * blit->height) >> dword_shift; - /* Add in a command for every 16 dwords */ - dwords += ( ( dwords + 15 ) / 16 ); buf->used = dwords << 2; - /* Blit via the host data registers (gui-master) - * Add state setup at the start of the buffer -- - * the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET + /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, + * continuation buffers? + */ + + /* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require + * a register command every 16 dwords. State setup is added at the start of the + * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET */ DMAOUTREG( MACH64_Z_CNTL, 0 ); DMAOUTREG( MACH64_SCALE_3D_CNTL, 0 ); @@ -510,8 +512,8 @@ static int mach64_dma_dispatch_blit( drm_device_t *dev, DRM_DEBUG( "%s: %d bytes\n", __FUNCTION__, buf->used ); /* Add the buffer to the queue */ - DMAADVANCE( dev_priv ); - + DMAADVANCEHOSTDATA( dev_priv ); + dev_priv->sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC);