parent
70bba11bc7
commit
6c04185857
|
@ -299,7 +299,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
|
||||||
cmd->size, dev, 1))) {
|
cmd->size, dev, 1))) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
|
vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
|
||||||
if (vb == NULL) {
|
if (vb == NULL) {
|
||||||
return DRM_ERR(EAGAIN);
|
return DRM_ERR(EAGAIN);
|
||||||
|
@ -433,70 +433,46 @@ static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
|
||||||
* modifying the pause address stored in the buffer itself. If
|
* modifying the pause address stored in the buffer itself. If
|
||||||
* the regulator has already paused, restart it.
|
* the regulator has already paused, restart it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int via_hook_segment(drm_via_private_t *dev_priv,
|
static int via_hook_segment(drm_via_private_t *dev_priv,
|
||||||
uint32_t pause_addr_hi, uint32_t pause_addr_lo,
|
uint32_t pause_addr_hi, uint32_t pause_addr_lo,
|
||||||
int no_pci_fire)
|
int no_pci_fire)
|
||||||
{
|
{
|
||||||
int paused, count;
|
int paused, count;
|
||||||
volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
|
volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
|
||||||
|
uint32_t reader,ptr;
|
||||||
via_flush_write_combine();
|
|
||||||
while(! *(via_get_dma(dev_priv)-1));
|
|
||||||
*dev_priv->last_pause_ptr = pause_addr_lo;
|
|
||||||
via_flush_write_combine();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The below statement is inserted to really force the flush.
|
|
||||||
* Not sure it is needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while(! *dev_priv->last_pause_ptr);
|
|
||||||
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
|
|
||||||
while(! *dev_priv->last_pause_ptr);
|
|
||||||
|
|
||||||
|
|
||||||
paused = 0;
|
paused = 0;
|
||||||
count = 20;
|
via_flush_write_combine();
|
||||||
|
*dev_priv->last_pause_ptr = pause_addr_lo;
|
||||||
|
via_flush_write_combine();
|
||||||
|
reader = *(dev_priv->hw_addr_ptr);
|
||||||
|
ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
|
||||||
|
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
|
||||||
|
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
|
||||||
|
|
||||||
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
|
if ((ptr - reader) <= dev_priv->dma_diff ) {
|
||||||
if ((count <= 8) && (count >= 0)) {
|
count = 10000000;
|
||||||
uint32_t rgtr, ptr;
|
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
|
||||||
rgtr = *(dev_priv->hw_addr_ptr);
|
|
||||||
ptr = ((volatile char *)dev_priv->last_pause_ptr -
|
|
||||||
dev_priv->dma_ptr) + dev_priv->dma_offset +
|
|
||||||
(uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
|
|
||||||
if (rgtr <= ptr) {
|
|
||||||
DRM_ERROR
|
|
||||||
("Command regulator\npaused at count %d, address %x, "
|
|
||||||
"while current pause address is %x.\n"
|
|
||||||
"Please mail this message to "
|
|
||||||
"<unichrome-devel@lists.sourceforge.net>\n", count,
|
|
||||||
rgtr, ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paused && !no_pci_fire) {
|
if (paused && !no_pci_fire) {
|
||||||
uint32_t rgtr,ptr;
|
reader = *(dev_priv->hw_addr_ptr);
|
||||||
uint32_t ptr_low;
|
if ((ptr - reader) == dev_priv->dma_diff) {
|
||||||
|
|
||||||
count = 1000000;
|
/*
|
||||||
while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
|
* There is a concern that these writes may stall the PCI bus
|
||||||
&& count--);
|
* if the GPU is not idle. However, idling the GPU first
|
||||||
|
* doesn't make a difference.
|
||||||
rgtr = *(dev_priv->hw_addr_ptr);
|
*/
|
||||||
ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
|
|
||||||
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
|
|
||||||
|
|
||||||
|
|
||||||
ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ?
|
|
||||||
ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
|
|
||||||
if (rgtr <= ptr && rgtr >= ptr_low) {
|
|
||||||
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
|
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
|
||||||
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
|
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
|
||||||
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
|
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
|
||||||
VIA_READ(VIA_REG_TRANSPACE);
|
VIA_READ(VIA_REG_TRANSPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paused;
|
return paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,6 +481,9 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
|
||||||
static int via_wait_idle(drm_via_private_t * dev_priv)
|
static int via_wait_idle(drm_via_private_t * dev_priv)
|
||||||
{
|
{
|
||||||
int count = 10000000;
|
int count = 10000000;
|
||||||
|
|
||||||
|
while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
|
||||||
|
|
||||||
while (count-- && (VIA_READ(VIA_REG_STATUS) &
|
while (count-- && (VIA_READ(VIA_REG_STATUS) &
|
||||||
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
|
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
|
||||||
VIA_3D_ENG_BUSY))) ;
|
VIA_3D_ENG_BUSY))) ;
|
||||||
|
@ -551,7 +530,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
||||||
uint32_t end_addr, end_addr_lo;
|
uint32_t end_addr, end_addr_lo;
|
||||||
uint32_t command;
|
uint32_t command;
|
||||||
uint32_t agp_base;
|
uint32_t agp_base;
|
||||||
|
uint32_t ptr;
|
||||||
|
uint32_t reader;
|
||||||
|
int count;
|
||||||
|
|
||||||
dev_priv->dma_low = 0;
|
dev_priv->dma_low = 0;
|
||||||
|
|
||||||
|
@ -581,6 +562,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
||||||
DRM_WRITEMEMORYBARRIER();
|
DRM_WRITEMEMORYBARRIER();
|
||||||
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
|
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
|
||||||
VIA_READ(VIA_REG_TRANSPACE);
|
VIA_READ(VIA_REG_TRANSPACE);
|
||||||
|
|
||||||
|
dev_priv->dma_diff = 0;
|
||||||
|
|
||||||
|
count = 10000000;
|
||||||
|
while (!(VIA_READ(0x41c) & 0x80000000) && count--);
|
||||||
|
|
||||||
|
reader = *(dev_priv->hw_addr_ptr);
|
||||||
|
ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
|
||||||
|
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the difference between where we tell the
|
||||||
|
* command reader to pause and where it actually pauses.
|
||||||
|
* This differs between hw implementation so we need to
|
||||||
|
* detect it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dev_priv->dma_diff = ptr - reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
|
static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
|
||||||
|
@ -598,20 +597,18 @@ static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
|
||||||
uint32_t *vb = via_get_dma(dev_priv);
|
uint32_t *vb = via_get_dma(dev_priv);
|
||||||
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
||||||
SetReg2DAGP(0x10, 0 | (0 << 16));
|
SetReg2DAGP(0x10, 0 | (0 << 16));
|
||||||
SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
|
SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
||||||
{
|
{
|
||||||
uint32_t agp_base;
|
uint32_t agp_base;
|
||||||
uint32_t pause_addr_lo, pause_addr_hi;
|
uint32_t pause_addr_lo, pause_addr_hi;
|
||||||
uint32_t jump_addr_lo, jump_addr_hi;
|
uint32_t jump_addr_lo, jump_addr_hi;
|
||||||
volatile uint32_t *last_pause_ptr;
|
volatile uint32_t *last_pause_ptr;
|
||||||
uint32_t dma_low_save1, dma_low_save2;
|
|
||||||
|
|
||||||
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
||||||
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
||||||
&jump_addr_lo, 0);
|
&jump_addr_lo, 0);
|
||||||
|
|
||||||
dev_priv->dma_wrap = dev_priv->dma_low;
|
dev_priv->dma_wrap = dev_priv->dma_low;
|
||||||
|
@ -627,38 +624,14 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
via_dummy_bitblt(dev_priv);
|
via_dummy_bitblt(dev_priv);
|
||||||
via_dummy_bitblt(dev_priv);
|
via_dummy_bitblt(dev_priv);
|
||||||
|
last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
last_pause_ptr =
|
|
||||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
|
||||||
&pause_addr_lo, 0) -1;
|
&pause_addr_lo, 0) -1;
|
||||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
&pause_addr_lo, 0);
|
|
||||||
|
|
||||||
*last_pause_ptr = pause_addr_lo;
|
|
||||||
dma_low_save1 = dev_priv->dma_low;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now, set a trap that will pause the regulator if it tries to rerun the old
|
|
||||||
* command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
|
|
||||||
* and reissues the jump command over PCI, while the regulator has already taken the jump
|
|
||||||
* and actually paused at the current buffer end).
|
|
||||||
* There appears to be no other way to detect this condition, since the hw_addr_pointer
|
|
||||||
* does not seem to get updated immediately when a jump occurs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
last_pause_ptr =
|
|
||||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
|
||||||
&pause_addr_lo, 0) -1;
|
|
||||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
|
||||||
&pause_addr_lo, 0);
|
&pause_addr_lo, 0);
|
||||||
*last_pause_ptr = pause_addr_lo;
|
*last_pause_ptr = pause_addr_lo;
|
||||||
|
|
||||||
dma_low_save2 = dev_priv->dma_low;
|
|
||||||
dev_priv->dma_low = dma_low_save1;
|
|
||||||
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||||
dev_priv->dma_low = dma_low_save2;
|
|
||||||
via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,11 @@
|
||||||
* backwards incompatibilities, (which should be avoided whenever possible).
|
* backwards incompatibilities, (which should be avoided whenever possible).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VIA_DRM_DRIVER_DATE "20061227"
|
#define VIA_DRM_DRIVER_DATE "20070202"
|
||||||
|
|
||||||
#define VIA_DRM_DRIVER_MAJOR 2
|
#define VIA_DRM_DRIVER_MAJOR 2
|
||||||
#define VIA_DRM_DRIVER_MINOR 11
|
#define VIA_DRM_DRIVER_MINOR 11
|
||||||
#define VIA_DRM_DRIVER_PATCHLEVEL 0
|
#define VIA_DRM_DRIVER_PATCHLEVEL 1
|
||||||
#define VIA_DRM_DRIVER_VERSION (((VIA_DRM_DRIVER_MAJOR) << 16) | (VIA_DRM_DRIVER_MINOR))
|
#define VIA_DRM_DRIVER_VERSION (((VIA_DRM_DRIVER_MAJOR) << 16) | (VIA_DRM_DRIVER_MINOR))
|
||||||
|
|
||||||
#define VIA_NR_SAREA_CLIPRECTS 8
|
#define VIA_NR_SAREA_CLIPRECTS 8
|
||||||
|
|
|
@ -102,6 +102,7 @@ typedef struct drm_via_private {
|
||||||
#ifdef VIA_HAVE_DMABLIT
|
#ifdef VIA_HAVE_DMABLIT
|
||||||
drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
|
drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
|
||||||
#endif
|
#endif
|
||||||
|
uint32_t dma_diff;
|
||||||
} drm_via_private_t;
|
} drm_via_private_t;
|
||||||
|
|
||||||
enum via_family {
|
enum via_family {
|
||||||
|
|
Loading…
Reference in New Issue