Reworked the jump-code in via_dma.c. The command regulator now seems to
pause correctly after a jump. Removed the debug message from within the interrupt handler of via_irq.cmain
parent
08758b2fb7
commit
9409d8231c
|
@ -8,14 +8,17 @@
|
||||||
* Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
|
* Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
|
* Copyright 2004 The Unichrome project.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
#include "via_drm.h"
|
#include "via_drm.h"
|
||||||
#include "via_drv.h"
|
#include "via_drv.h"
|
||||||
|
#include "via_3d_reg.h"
|
||||||
|
|
||||||
#define VIA_2D_CMD 0xF0000000
|
|
||||||
#define via_flush_write_combine() DRM_MEMORYBARRIER()
|
#define via_flush_write_combine() DRM_MEMORYBARRIER()
|
||||||
|
|
||||||
#define VIA_OUT_RING_QW(w1,w2) \
|
#define VIA_OUT_RING_QW(w1,w2) \
|
||||||
|
@ -61,12 +64,12 @@ static int via_check_command_stream(const uint32_t * buf, unsigned int size)
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
offset = *buf;
|
offset = *buf;
|
||||||
buf += 2;
|
buf += 2;
|
||||||
if ((offset > ((0x3FF >> 2) | VIA_2D_CMD)) &&
|
if ((offset > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
|
||||||
(offset < ((0xC00 >> 2) | VIA_2D_CMD))) {
|
(offset < ((0xC00 >> 2) | HALCYON_HEADER1))) {
|
||||||
DRM_ERROR
|
DRM_ERROR
|
||||||
("Attempt to access Burst Command / 3D Area.\n");
|
("Attempt to access Burst Command / 3D Area.\n");
|
||||||
return DRM_ERR(EINVAL);
|
return DRM_ERR(EINVAL);
|
||||||
} else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) {
|
} else if (offset > ((0xDFF >> 2) | HALCYON_HEADER1)) {
|
||||||
DRM_ERROR("Attempt to access DMA or VGA registers.\n");
|
DRM_ERROR("Attempt to access DMA or VGA registers.\n");
|
||||||
return DRM_ERR(EINVAL);
|
return DRM_ERR(EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -291,7 +294,7 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,
|
||||||
|
|
||||||
size >>= 3;
|
size >>= 3;
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
offset = (*regbuf++ & ~VIA_2D_CMD) << 2;
|
offset = (*regbuf++ & ~HALCYON_HEADER1) << 2;
|
||||||
value = *regbuf++;
|
value = *regbuf++;
|
||||||
VIA_WRITE(offset, value);
|
VIA_WRITE(offset, value);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +359,6 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
#include "via_3d_reg.h"
|
|
||||||
|
|
||||||
#define CMDBUF_ALIGNMENT_SIZE (0x100)
|
#define CMDBUF_ALIGNMENT_SIZE (0x100)
|
||||||
#define CMDBUF_ALIGNMENT_MASK (0xff)
|
#define CMDBUF_ALIGNMENT_MASK (0xff)
|
||||||
|
@ -373,7 +375,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
|
||||||
#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
|
#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
|
||||||
|
|
||||||
#define SetReg2DAGP(nReg, nData) { \
|
#define SetReg2DAGP(nReg, nData) { \
|
||||||
*((uint32_t *)(vb)) = ((nReg) >> 2) | 0xF0000000; \
|
*((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \
|
||||||
*((uint32_t *)(vb) + 1) = (nData); \
|
*((uint32_t *)(vb) + 1) = (nData); \
|
||||||
vb = ((uint32_t *)vb) + 2; \
|
vb = ((uint32_t *)vb) + 2; \
|
||||||
dev_priv->dma_low +=8; \
|
dev_priv->dma_low +=8; \
|
||||||
|
@ -534,106 +536,47 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
||||||
static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
|
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);
|
||||||
/* GEDST */
|
|
||||||
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
||||||
/* GEWD */
|
|
||||||
SetReg2DAGP(0x10, 0 | (0 << 16));
|
SetReg2DAGP(0x10, 0 | (0 << 16));
|
||||||
/* BITBLT */
|
|
||||||
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, pause_addr_lo, pause_addr_hi;
|
uint32_t pause_addr_lo, pause_addr_hi;
|
||||||
uint32_t start_addr;
|
uint32_t jump_addr_lo, jump_addr_hi;
|
||||||
uint32_t end_addr, end_addr_lo;
|
volatile uint32_t *last_pause_ptr;
|
||||||
uint32_t *vb;
|
|
||||||
uint32_t qw_pad_count;
|
|
||||||
uint32_t command;
|
|
||||||
uint32_t jump_addr, jump_addr_lo, jump_addr_hi;
|
|
||||||
|
|
||||||
/* Seems like Unichrome has bug that when the PAUSE register is
|
|
||||||
* set in the AGP command stream immediately after a PCI write to
|
|
||||||
* the same register, the command regulator goes into a looping
|
|
||||||
* state. Prepending a BitBLT command to stall the command
|
|
||||||
* regulator for a moment seems to solve the problem.
|
|
||||||
*/
|
|
||||||
via_cmdbuf_wait(dev_priv, 48);
|
|
||||||
via_dummy_bitblt(dev_priv);
|
|
||||||
|
|
||||||
via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
|
|
||||||
|
|
||||||
/* At end of buffer, rewind with a JUMP command. */
|
|
||||||
vb = via_get_dma(dev_priv);
|
|
||||||
|
|
||||||
*vb++ = HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
|
|
||||||
(VIA_REG_TRANSPACE >> 2);
|
|
||||||
*vb++ = (HC_ParaType_PreCR << 16);
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
|
|
||||||
((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
|
|
||||||
|
|
||||||
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
||||||
start_addr = agp_base;
|
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
||||||
end_addr = agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
|
&jump_addr_lo);
|
||||||
|
|
||||||
jump_addr = end_addr;
|
|
||||||
jump_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_JUMP |
|
|
||||||
(jump_addr & 0xffffff));
|
|
||||||
jump_addr_hi = ((HC_SubA_HAGPBpH << 24) | (jump_addr >> 24));
|
|
||||||
|
|
||||||
end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
|
|
||||||
command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
|
|
||||||
((end_addr & 0xff000000) >> 16));
|
|
||||||
|
|
||||||
*vb++ = command;
|
|
||||||
*vb++ = end_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
|
|
||||||
|
|
||||||
/* Now at beginning of buffer, make sure engine will pause here. */
|
|
||||||
dev_priv->dma_low = 0;
|
dev_priv->dma_low = 0;
|
||||||
if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
|
if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
|
||||||
DRM_ERROR("via_cmdbuf_jump failed\n");
|
DRM_ERROR("via_cmdbuf_jump failed\n");
|
||||||
}
|
}
|
||||||
vb = via_get_dma(dev_priv);
|
|
||||||
|
|
||||||
end_addr = agp_base + dev_priv->dma_high;
|
/*
|
||||||
|
* The command regulator needs to stall for a while since it probably
|
||||||
|
* had a concussion during the jump... It will stall at the second
|
||||||
|
* bitblt since the 2D engine is busy with the first.
|
||||||
|
*/
|
||||||
|
|
||||||
end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
|
via_dummy_bitblt(dev_priv);
|
||||||
command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
|
via_dummy_bitblt(dev_priv);
|
||||||
((end_addr & 0xff000000) >> 16));
|
last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
|
&pause_addr_lo) -1;
|
||||||
|
|
||||||
qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
|
/*
|
||||||
((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
|
* The regulator may still be suffering from the shock of the jump.
|
||||||
|
* Add another pause command to make sure it really will get itself together
|
||||||
|
* and pause.
|
||||||
|
*/
|
||||||
|
|
||||||
pause_addr = agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
|
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
pause_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_PAUSE |
|
&pause_addr_lo);
|
||||||
(pause_addr & 0xffffff));
|
*last_pause_ptr = pause_addr_lo;
|
||||||
pause_addr_hi = ((HC_SubA_HAGPBpH << 24) | (pause_addr >> 24));
|
|
||||||
|
|
||||||
*vb++ = HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
|
|
||||||
(VIA_REG_TRANSPACE >> 2);
|
|
||||||
*vb++ = (HC_ParaType_PreCR << 16);
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
*vb++ = pause_addr_hi;
|
|
||||||
*vb++ = pause_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
*vb++ = command;
|
|
||||||
*vb++ = end_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
vb = via_align_buffer(dev_priv, vb, qw_pad_count - 4);
|
|
||||||
|
|
||||||
*vb++ = pause_addr_hi;
|
|
||||||
*vb++ = pause_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,9 +584,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
||||||
|
|
||||||
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
|
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
|
||||||
{
|
{
|
||||||
/* via_cmdbuf_jump(dev_priv); */
|
via_cmdbuf_jump(dev_priv);
|
||||||
via_cmdbuf_reset(dev_priv);
|
|
||||||
via_cmdbuf_start(dev_priv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
|
static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
|
||||||
|
|
|
@ -28,11 +28,11 @@
|
||||||
|
|
||||||
#define DRIVER_NAME "via"
|
#define DRIVER_NAME "via"
|
||||||
#define DRIVER_DESC "VIA Unichrome"
|
#define DRIVER_DESC "VIA Unichrome"
|
||||||
#define DRIVER_DATE "20041030"
|
#define DRIVER_DATE "20041101"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 2
|
#define DRIVER_MAJOR 2
|
||||||
#define DRIVER_MINOR 0
|
#define DRIVER_MINOR 0
|
||||||
#define DRIVER_PATCHLEVEL 2
|
#define DRIVER_PATCHLEVEL 3
|
||||||
|
|
||||||
typedef struct drm_via_ring_buffer {
|
typedef struct drm_via_ring_buffer {
|
||||||
drm_map_t map;
|
drm_map_t map;
|
||||||
|
|
|
@ -53,7 +53,6 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||||
DRM_DEBUG("viadrv_irq_handler Status: %x\n", status);
|
|
||||||
if (status & VIA_IRQ_VBI_PENDING) {
|
if (status & VIA_IRQ_VBI_PENDING) {
|
||||||
atomic_inc(&dev->vbl_received);
|
atomic_inc(&dev->vbl_received);
|
||||||
DRM_WAKEUP(&dev->vbl_queue);
|
DRM_WAKEUP(&dev->vbl_queue);
|
||||||
|
|
|
@ -30,11 +30,11 @@
|
||||||
|
|
||||||
#define DRIVER_NAME "via"
|
#define DRIVER_NAME "via"
|
||||||
#define DRIVER_DESC "VIA Unichrome"
|
#define DRIVER_DESC "VIA Unichrome"
|
||||||
#define DRIVER_DATE "20041030"
|
#define DRIVER_DATE "20041101"
|
||||||
|
|
||||||
#define DRIVER_MAJOR 2
|
#define DRIVER_MAJOR 2
|
||||||
#define DRIVER_MINOR 0
|
#define DRIVER_MINOR 0
|
||||||
#define DRIVER_PATCHLEVEL 2
|
#define DRIVER_PATCHLEVEL 3
|
||||||
|
|
||||||
#define DRIVER_IOCTLS \
|
#define DRIVER_IOCTLS \
|
||||||
[DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \
|
[DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \
|
||||||
|
|
123
shared/via_dma.c
123
shared/via_dma.c
|
@ -8,6 +8,9 @@
|
||||||
* Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
|
* Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
|
* Copyright 2004 The Unichrome project.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "via.h"
|
#include "via.h"
|
||||||
|
@ -15,8 +18,8 @@
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
#include "via_drm.h"
|
#include "via_drm.h"
|
||||||
#include "via_drv.h"
|
#include "via_drv.h"
|
||||||
|
#include "via_3d_reg.h"
|
||||||
|
|
||||||
#define VIA_2D_CMD 0xF0000000
|
|
||||||
#define via_flush_write_combine() DRM_MEMORYBARRIER()
|
#define via_flush_write_combine() DRM_MEMORYBARRIER()
|
||||||
|
|
||||||
#define VIA_OUT_RING_QW(w1,w2) \
|
#define VIA_OUT_RING_QW(w1,w2) \
|
||||||
|
@ -62,12 +65,12 @@ static int via_check_command_stream(const uint32_t * buf, unsigned int size)
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
offset = *buf;
|
offset = *buf;
|
||||||
buf += 2;
|
buf += 2;
|
||||||
if ((offset > ((0x3FF >> 2) | VIA_2D_CMD)) &&
|
if ((offset > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
|
||||||
(offset < ((0xC00 >> 2) | VIA_2D_CMD))) {
|
(offset < ((0xC00 >> 2) | HALCYON_HEADER1))) {
|
||||||
DRM_ERROR
|
DRM_ERROR
|
||||||
("Attempt to access Burst Command / 3D Area.\n");
|
("Attempt to access Burst Command / 3D Area.\n");
|
||||||
return DRM_ERR(EINVAL);
|
return DRM_ERR(EINVAL);
|
||||||
} else if (offset > ((0xDFF >> 2) | VIA_2D_CMD)) {
|
} else if (offset > ((0xDFF >> 2) | HALCYON_HEADER1)) {
|
||||||
DRM_ERROR("Attempt to access DMA or VGA registers.\n");
|
DRM_ERROR("Attempt to access DMA or VGA registers.\n");
|
||||||
return DRM_ERR(EINVAL);
|
return DRM_ERR(EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -292,7 +295,7 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf,
|
||||||
|
|
||||||
size >>= 3;
|
size >>= 3;
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
offset = (*regbuf++ & ~VIA_2D_CMD) << 2;
|
offset = (*regbuf++ & ~HALCYON_HEADER1) << 2;
|
||||||
value = *regbuf++;
|
value = *regbuf++;
|
||||||
VIA_WRITE(offset, value);
|
VIA_WRITE(offset, value);
|
||||||
}
|
}
|
||||||
|
@ -357,7 +360,6 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
#include "via_3d_reg.h"
|
|
||||||
|
|
||||||
#define CMDBUF_ALIGNMENT_SIZE (0x100)
|
#define CMDBUF_ALIGNMENT_SIZE (0x100)
|
||||||
#define CMDBUF_ALIGNMENT_MASK (0xff)
|
#define CMDBUF_ALIGNMENT_MASK (0xff)
|
||||||
|
@ -374,7 +376,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
|
||||||
#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
|
#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
|
||||||
|
|
||||||
#define SetReg2DAGP(nReg, nData) { \
|
#define SetReg2DAGP(nReg, nData) { \
|
||||||
*((uint32_t *)(vb)) = ((nReg) >> 2) | 0xF0000000; \
|
*((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \
|
||||||
*((uint32_t *)(vb) + 1) = (nData); \
|
*((uint32_t *)(vb) + 1) = (nData); \
|
||||||
vb = ((uint32_t *)vb) + 2; \
|
vb = ((uint32_t *)vb) + 2; \
|
||||||
dev_priv->dma_low +=8; \
|
dev_priv->dma_low +=8; \
|
||||||
|
@ -535,11 +537,8 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
||||||
static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
|
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);
|
||||||
/* GEDST */
|
|
||||||
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
SetReg2DAGP(0x0C, (0 | (0 << 16)));
|
||||||
/* GEWD */
|
|
||||||
SetReg2DAGP(0x10, 0 | (0 << 16));
|
SetReg2DAGP(0x10, 0 | (0 << 16));
|
||||||
/* BITBLT */
|
|
||||||
SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
|
SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,95 +546,39 @@ static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
|
||||||
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, pause_addr_lo, pause_addr_hi;
|
uint32_t pause_addr_lo, pause_addr_hi;
|
||||||
uint32_t start_addr;
|
uint32_t jump_addr_lo, jump_addr_hi;
|
||||||
uint32_t end_addr, end_addr_lo;
|
volatile uint32_t *last_pause_ptr;
|
||||||
uint32_t *vb;
|
|
||||||
uint32_t qw_pad_count;
|
|
||||||
uint32_t command;
|
|
||||||
uint32_t jump_addr, jump_addr_lo, jump_addr_hi;
|
|
||||||
|
|
||||||
/* Seems like Unichrome has bug that when the PAUSE register is
|
|
||||||
* set in the AGP command stream immediately after a PCI write to
|
|
||||||
* the same register, the command regulator goes into a looping
|
|
||||||
* state. Prepending a BitBLT command to stall the command
|
|
||||||
* regulator for a moment seems to solve the problem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
via_cmdbuf_wait(dev_priv, 48);
|
|
||||||
via_dummy_bitblt(dev_priv);
|
|
||||||
|
|
||||||
via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
|
|
||||||
|
|
||||||
/* At end of buffer, rewind with a JUMP command. */
|
|
||||||
vb = via_get_dma(dev_priv);
|
|
||||||
|
|
||||||
*vb++ = HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
|
|
||||||
(VIA_REG_TRANSPACE >> 2);
|
|
||||||
*vb++ = (HC_ParaType_PreCR << 16);
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
|
|
||||||
((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
|
|
||||||
|
|
||||||
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
||||||
start_addr = agp_base;
|
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
||||||
end_addr = agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
|
&jump_addr_lo);
|
||||||
|
|
||||||
jump_addr = end_addr;
|
|
||||||
jump_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_JUMP |
|
|
||||||
(jump_addr & 0xffffff));
|
|
||||||
jump_addr_hi = ((HC_SubA_HAGPBpH << 24) | (jump_addr >> 24));
|
|
||||||
|
|
||||||
end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
|
|
||||||
command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
|
|
||||||
((end_addr & 0xff000000) >> 16));
|
|
||||||
|
|
||||||
*vb++ = command;
|
|
||||||
*vb++ = end_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
|
|
||||||
|
|
||||||
/* Now at beginning of buffer, make sure engine will pause here. */
|
|
||||||
dev_priv->dma_low = 0;
|
dev_priv->dma_low = 0;
|
||||||
if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
|
if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
|
||||||
DRM_ERROR("via_cmdbuf_jump failed\n");
|
DRM_ERROR("via_cmdbuf_jump failed\n");
|
||||||
}
|
}
|
||||||
vb = via_get_dma(dev_priv);
|
|
||||||
|
|
||||||
end_addr = agp_base + dev_priv->dma_high;
|
/*
|
||||||
|
* The command regulator needs to stall for a while since it probably
|
||||||
|
* had a concussion during the jump... It will stall at the second
|
||||||
|
* bitblt since the 2D engine is busy with the first.
|
||||||
|
*/
|
||||||
|
|
||||||
end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
|
via_dummy_bitblt(dev_priv);
|
||||||
command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
|
via_dummy_bitblt(dev_priv);
|
||||||
((end_addr & 0xff000000) >> 16));
|
last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
|
&pause_addr_lo) -1;
|
||||||
|
|
||||||
qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
|
/*
|
||||||
((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
|
* The regulator may still be suffering from the shock of the jump.
|
||||||
|
* Add another pause command to make sure it really will get itself together
|
||||||
|
* and pause.
|
||||||
|
*/
|
||||||
|
|
||||||
pause_addr = agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
|
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||||
pause_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_PAUSE |
|
&pause_addr_lo);
|
||||||
(pause_addr & 0xffffff));
|
*last_pause_ptr = pause_addr_lo;
|
||||||
pause_addr_hi = ((HC_SubA_HAGPBpH << 24) | (pause_addr >> 24));
|
|
||||||
|
|
||||||
*vb++ = HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
|
|
||||||
(VIA_REG_TRANSPACE >> 2);
|
|
||||||
*vb++ = (HC_ParaType_PreCR << 16);
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
*vb++ = pause_addr_hi;
|
|
||||||
*vb++ = pause_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
*vb++ = command;
|
|
||||||
*vb++ = end_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
|
|
||||||
vb = via_align_buffer(dev_priv, vb, qw_pad_count - 4);
|
|
||||||
|
|
||||||
*vb++ = pause_addr_hi;
|
|
||||||
*vb++ = pause_addr_lo;
|
|
||||||
dev_priv->dma_low += 8;
|
|
||||||
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,9 +586,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
||||||
|
|
||||||
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
|
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
|
||||||
{
|
{
|
||||||
/* via_cmdbuf_jump(dev_priv); */
|
via_cmdbuf_jump(dev_priv);
|
||||||
via_cmdbuf_reset(dev_priv);
|
|
||||||
via_cmdbuf_start(dev_priv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
|
static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
|
||||||
|
|
|
@ -54,7 +54,6 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||||
DRM_DEBUG("viadrv_irq_handler Status: %x\n", status);
|
|
||||||
if (status & VIA_IRQ_VBI_PENDING) {
|
if (status & VIA_IRQ_VBI_PENDING) {
|
||||||
atomic_inc(&dev->vbl_received);
|
atomic_inc(&dev->vbl_received);
|
||||||
DRM_WAKEUP(&dev->vbl_queue);
|
DRM_WAKEUP(&dev->vbl_queue);
|
||||||
|
|
Loading…
Reference in New Issue