summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2008-07-31 15:18:32 -0400
committerKristian Høgsberg <krh@redhat.com>2008-07-31 15:18:32 -0400
commit5052e966ec7fe5146c2d73b90482003619add5da (patch)
treea48e771871fd64a2892f5ce75e6e309b03db5e06 /shared-core
parent6d4e147480a334d32fa59c7fde53e10d7ab6e106 (diff)
parent95c02743c96ca9e959f68a6e942206bdfadae53a (diff)
Merge commit 'origin/master' into modesetting-gem
Conflicts: linux-core/Makefile.kernel linux-core/ati_pcigart.c linux-core/drm_compat.h linux-core/drm_irq.c linux-core/drm_lock.c linux-core/i915_drv.c shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c shared-core/nouveau_mem.c shared-core/radeon_cp.c shared-core/radeon_drv.h
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/drm.h2
-rw-r--r--shared-core/drm_pciids.txt15
-rw-r--r--shared-core/i915_dma.c1
-rw-r--r--shared-core/i915_drv.h66
-rw-r--r--shared-core/i915_init.c74
-rw-r--r--shared-core/i915_irq.c175
-rw-r--r--shared-core/i915_suspend.c520
-rw-r--r--shared-core/nouveau_fifo.c2
-rw-r--r--shared-core/nouveau_mem.c1
-rw-r--r--shared-core/nv04_fifo.c4
-rw-r--r--shared-core/r300_cmdbuf.c214
-rw-r--r--shared-core/r300_reg.h229
-rw-r--r--shared-core/radeon_cp.c58
-rw-r--r--shared-core/radeon_drv.h45
-rw-r--r--shared-core/radeon_irq.c57
-rw-r--r--shared-core/radeon_mem.c8
-rw-r--r--shared-core/xgi_drm.h4
17 files changed, 1124 insertions, 351 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 7aba2939..dd03bf9b 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -1330,7 +1330,7 @@ struct drm_mode_crtc_lut {
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding)
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding)
-#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather)
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather)
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt
index b95bc8f2..0c45b4c1 100644
--- a/shared-core/drm_pciids.txt
+++ b/shared-core/drm_pciids.txt
@@ -83,7 +83,6 @@
0x1002 0x5460 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X300 M22"
0x1002 0x5462 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X600 SE M24C"
0x1002 0x5464 CHIP_RV380|RADEON_IS_MOBILITY "ATI FireGL M22 GL 5464"
-0x1002 0x5657 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X550XTX"
0x1002 0x5548 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800"
0x1002 0x5549 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 Pro"
0x1002 0x554A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 XT PE"
@@ -101,9 +100,10 @@
0x1002 0x564F CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 XL M26"
0x1002 0x5652 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26"
0x1002 0x5653 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26"
+0x1002 0x5657 CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon X550XTX"
0x1002 0x5834 CHIP_RS300|RADEON_IS_IGP "ATI Radeon RS300 9100 IGP"
0x1002 0x5835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS300 Mobility IGP"
-0x1002 0x5954 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI RS480 XPRESS 200G"
+0x1002 0x5954 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_IGPGART "ATI RS480 XPRESS 200G"
0x1002 0x5955 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon XPRESS 200M 5955"
0x1002 0x5974 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS482 XPRESS 200"
0x1002 0x5975 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS485 XPRESS 1100 IGP"
@@ -113,8 +113,10 @@
0x1002 0x5964 CHIP_RV280 "ATI Radeon RV280 9200 SE"
0x1002 0x5965 CHIP_RV280 "ATI FireMV 2200 PCI"
0x1002 0x5969 CHIP_RV100 "ATI ES1000 RN50"
-0x1002 0x5a61 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200"
-0x1002 0x5a62 CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200M"
+0x1002 0x5a41 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART "ATI Radeon XPRESS 200 5A41 (PCIE)"
+0x1002 0x5a42 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon XPRESS 200M 5A42 (PCIE)"
+0x1002 0x5a61 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200"
+0x1002 0x5a62 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200M"
0x1002 0x5b60 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X300 SE"
0x1002 0x5b62 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X600 Pro"
0x1002 0x5b63 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X550"
@@ -396,7 +398,10 @@
0x8086 0x29C2 CHIP_I9XX|CHIP_I915 "Intel G33"
0x8086 0x29B2 CHIP_I9XX|CHIP_I915 "Intel Q35"
0x8086 0x29D2 CHIP_I9XX|CHIP_I915 "Intel Q33"
-0x8086 0x2A42 CHIP_I9XX|CHIP_I965 "Intel Integrated Graphics Device"
+0x8086 0x2A42 CHIP_I9XX|CHIP_I965 "Mobile Intel® GM45 Express Chipset"
+0x8086 0x2E02 CHIP_I9XX|CHIP_I965 "Intel Integrated Graphics Device"
+0x8086 0x2E12 CHIP_I9XX|CHIP_I965 "Intel Q45/Q43"
+0x8086 0x2E22 CHIP_I9XX|CHIP_I965 "Intel G45/G43"
[imagine]
0x105d 0x2309 IMAGINE_128 "Imagine 128"
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 09c53676..8d09828a 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -1049,6 +1049,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
" G33 hw status page\n");
return -ENOMEM;
}
+
dev_priv->hws_vaddr = dev_priv->hws_map.handle;
memset(dev_priv->hws_vaddr, 0, PAGE_SIZE);
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 17829a56..a0f73298 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -107,6 +107,23 @@ struct drm_i915_vbl_swap {
struct drm_minor *minor;
};
+
+#ifdef __linux__
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct intel_opregion {
+ struct opregion_header *header;
+ struct opregion_acpi *acpi;
+ struct opregion_swsci *swsci;
+ struct opregion_asle *asle;
+
+ int enabled;
+};
+#endif
+
struct drm_i915_master_private {
drm_local_map_t *sarea;
struct drm_i915_sarea *sarea_priv;
@@ -266,6 +283,10 @@ struct drm_i915_private {
struct work_struct user_interrupt_task;
+#ifdef __linux__
+ struct intel_opregion opregion;
+#endif
+
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;
@@ -480,6 +501,7 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(struct drm_device * dev);
extern int i915_driver_irq_postinstall(struct drm_device * dev);
extern void i915_driver_irq_uninstall(struct drm_device * dev);
+extern void i915_enable_interrupt(struct drm_device *dev);
extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
@@ -508,6 +530,11 @@ extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(struct drm_device * dev,
struct drm_file *file_priv,
struct mem_block *heap);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
#ifdef I915_HAVE_FENCE
/* i915_fence.c */
extern void i915_fence_handler(struct drm_device *dev);
@@ -580,6 +607,14 @@ void i915_gem_retire_work_handler(struct work_struct *work);
extern unsigned int i915_fbpercrtc;
#ifdef __linux__
+/* i915_opregion.c */
+extern int intel_opregion_init(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev);
+extern void opregion_asle_intr(struct drm_device *dev);
+extern void opregion_enable_asle(struct drm_device *dev);
+#endif
+
+#ifdef __linux__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
extern void intel_init_chipset_flush_compat(struct drm_device *dev);
extern void intel_fini_chipset_flush_compat(struct drm_device *dev);
@@ -596,12 +631,20 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+#define I915_READ8(reg) DRM_READ8(dev_priv->mmio_map, (reg))
+#define I915_WRITE8(reg,val) DRM_WRITE8(dev_priv->mmio_map, (reg), (val))
+
+#if defined(__FreeBSD__)
+typedef boolean_t bool;
+#endif
#define I915_VERBOSE 0
#define I915_RING_VALIDATE 0
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
+#define PRIMARY_RINGBUFFER_SIZE (128*1024)
+
#define RING_LOCALS unsigned int outring, ringmask, outcount; \
volatile char *virt;
@@ -740,7 +783,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
-#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) /* used to have 1<<22? */
+#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
+#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
#define MI_STORE_DWORD_INDEX_SHIFT 2
#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1)
@@ -805,8 +849,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define BLT_DEPTH_16_1555 (2<<24)
#define BLT_DEPTH_32 (3<<24)
#define BLT_ROP_GXCOPY (0xcc<<16)
-#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
-#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
+#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */
+#define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */
#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
#define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20)
@@ -862,6 +906,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
#define I915_DEBUG_INTERRUPT (1<<2)
#define I915_USER_INTERRUPT (1<<1)
+#define I915_ASLE_INTERRUPT (1<<0)
#define EIR 0x020b0
#define EMR 0x020b4
#define ESR 0x020b8
@@ -2050,11 +2095,18 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x29A2 || \
(dev)->pci_device == 0x2A02 || \
(dev)->pci_device == 0x2A12 || \
- (dev)->pci_device == 0x2A42)
+ (dev)->pci_device == 0x2A42 || \
+ (dev)->pci_device == 0x2E02 || \
+ (dev)->pci_device == 0x2E12 || \
+ (dev)->pci_device == 0x2E22)
#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
-#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
+#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
+
+#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
+ (dev)->pci_device == 0x2E12 || \
+ (dev)->pci_device == 0x2E22)
#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
(dev)->pci_device == 0x29B2 || \
@@ -2064,8 +2116,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
- IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
+ IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev))
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
#endif
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
index 3a652e8d..009d447b 100644
--- a/shared-core/i915_init.c
+++ b/shared-core/i915_init.c
@@ -269,7 +269,8 @@ out:
int i915_driver_load(struct drm_device *dev, unsigned long flags)
{
struct drm_i915_private *dev_priv;
- int ret = 0;
+ int ret = 0, num_pipes = 2;
+ u32 tmp;
dev_priv = drm_alloc(sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
if (dev_priv == NULL)
@@ -333,10 +334,51 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
#ifdef __linux__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
- intel_init_chipset_flush_compat(dev);
+ intel_init_chipset_flush_compat(dev);
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+ intel_opregion_init(dev);
#endif
#endif
+ tmp = I915_READ(PIPEASTAT);
+ I915_WRITE(PIPEASTAT, tmp);
+ tmp = I915_READ(PIPEBSTAT);
+ I915_WRITE(PIPEBSTAT, tmp);
+
+ atomic_set(&dev_priv->irq_received, 0);
+ I915_WRITE(HWSTAM, 0xeffe);
+ I915_WRITE(IMR, 0x0);
+ I915_WRITE(IER, 0x0);
+
+ DRM_SPININIT(&dev_priv->swaps_lock, "swap");
+ INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+ dev_priv->swaps_pending = 0;
+
+ DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
+ dev_priv->user_irq_refcount = 0;
+ dev_priv->irq_mask_reg = ~0;
+
+ ret = drm_vblank_init(dev, num_pipes);
+ if (ret)
+ goto out_rmmap;
+
+ ret = drm_hotplug_init(dev);
+ if (ret)
+ goto out_rmmap;
+
+ dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+ i915_enable_interrupt(dev);
+ DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+ /*
+ * Initialize the hardware status page IRQ location.
+ */
+
+ I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
+
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_load_modeset_init(dev);
if (ret < 0) {
@@ -344,6 +386,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto out_rmmap;
}
}
+
return 0;
out_rmmap:
@@ -357,6 +400,23 @@ int i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 temp;
+
+ dev_priv->vblank_pipe = 0;
+
+ dev_priv->irq_enabled = 0;
+
+ I915_WRITE(HWSTAM, 0xffffffff);
+ I915_WRITE(IMR, 0xffffffff);
+ I915_WRITE(IER, 0x0);
+
+ temp = I915_READ(PIPEASTAT);
+ I915_WRITE(PIPEASTAT, temp);
+ temp = I915_READ(PIPEBSTAT);
+ I915_WRITE(PIPEBSTAT, temp);
+ temp = I915_READ(IIR);
+ I915_WRITE(IIR, temp);
+
I915_WRITE(PRB0_CTL, 0);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
@@ -395,15 +455,17 @@ int i915_driver_unload(struct drm_device *dev)
i915_gem_lastclose(dev);
}
+ drm_rmmap(dev, dev_priv->mmio_map);
+
#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+ intel_opregion_free(dev);
+#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
- intel_init_chipset_flush_compat(dev);
+ intel_fini_chipset_flush_compat(dev);
#endif
#endif
- DRM_DEBUG("%p\n", dev_priv->mmio_map);
- drm_rmmap(dev, dev_priv->mmio_map);
-
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
dev->dev_private = NULL;
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index bad5ae29..b4004a8f 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -192,11 +192,11 @@ static void i915_vblank_tasklet(struct drm_device *dev)
u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
RING_LOCALS;
- if (sarea_priv->front_tiled) {
+ if (IS_I965G(dev) && sarea_priv->front_tiled) {
cmd |= XY_SRC_COPY_BLT_DST_TILED;
dst_pitch >>= 2;
}
- if (sarea_priv->back_tiled) {
+ if (IS_I965G(dev) && sarea_priv->back_tiled) {
cmd |= XY_SRC_COPY_BLT_SRC_TILED;
src_pitch >>= 2;
}
@@ -394,28 +394,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
}
}
-#if 0
-static int i915_in_vblank(struct drm_device *dev, int pipe)
-{
- struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- unsigned long pipedsl, vblank, vtotal;
- unsigned long vbl_start, vbl_end, cur_line;
-
- pipedsl = pipe ? PIPEBDSL : PIPEADSL;
- vblank = pipe ? VBLANK_B : VBLANK_A;
- vtotal = pipe ? VTOTAL_B : VTOTAL_A;
-
- vbl_start = I915_READ(vblank) & VBLANK_START_MASK;
- vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK;
-
- cur_line = I915_READ(pipedsl);
- if (cur_line >= vbl_start)
- return 1;
-
- return 0;
-}
-#endif
u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
@@ -449,22 +428,6 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
count = (high1 << 8) | low;
- /*
- * If we're in the middle of the vblank period, the
- * above regs won't have been updated yet, so return
- * an incremented count to stay accurate
- */
-#if 0
- if (i915_in_vblank(dev, pipe))
- count++;
-#endif
- /* count may be reset by other driver(e.g. 2D driver),
- we have no way to know if it is wrapped or resetted
- when count is zero. do a rough guess.
- */
- if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
- dev->last_vblank[pipe] = 0;
-
return count;
}
@@ -533,23 +496,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (dev->pdev->msi_enabled)
I915_WRITE(IMR, ~0);
iir = I915_READ(IIR);
-#if 0
- DRM_DEBUG("flag=%08x\n", iir);
-#endif
atomic_inc(&dev_priv->irq_received);
if (iir == 0) {
- DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
- iir,
- I915_READ(IMR),
- I915_READ(IER),
- I915_READ(PIPEASTAT),
- I915_READ(PIPEBSTAT));
if (dev->pdev->msi_enabled) {
- I915_WRITE(IMR,
- dev_priv->irq_mask_reg);
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IMR);
}
- return IRQ_NONE;
}
/*
@@ -588,6 +540,16 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
}
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+ if ((iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) &&
+ (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE))
+ opregion_asle_intr(dev);
+ if (iir & I915_ASLE_INTERRUPT)
+ opregion_asle_intr(dev);
+#endif
+#endif
+
if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
@@ -602,6 +564,11 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
drm_handle_vblank(dev, i915_get_plane(dev, 0));
}
+ /* The vblank interrupt gets enabled even if we didn't ask for
+ it, so make sure it's shut down again */
+ if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
+ pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE);
+
if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS)) {
vblank++;
@@ -917,9 +884,16 @@ void i915_enable_interrupt (struct drm_device *dev)
}
}
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+ opregion_enable_asle(dev);
+#endif
+#endif
+
I915_WRITE(IMR, dev_priv->irq_mask_reg);
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
(void) I915_READ (IER);
+
dev_priv->irq_enabled = 1;
}
@@ -929,20 +903,12 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_i915_vblank_pipe *pipe = data;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
- if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
- DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
- return -EINVAL;
- }
-
- dev_priv->vblank_pipe = pipe->pipe;
-
return 0;
}
@@ -1032,7 +998,13 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
- drm_update_vblank_count(dev, pipe);
+ /*
+ * We take the ref here and put it when the swap actually completes
+ * in the tasklet.
+ */
+ ret = drm_vblank_get(dev, pipe);
+ if (ret)
+ return ret;
curseq = drm_vblank_count(dev, pipe);
if (seqtype == _DRM_VBLANK_RELATIVE)
@@ -1043,6 +1015,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
swap->sequence = curseq + 1;
} else {
DRM_DEBUG("Missed target sequence\n");
+ drm_vblank_put(dev, pipe);
return -EINVAL;
}
}
@@ -1064,6 +1037,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
irqflags);
DRM_DEBUG("Invalid drawable ID %d\n",
swap->drawable);
+ drm_vblank_put(dev, pipe);
return -EINVAL;
}
@@ -1071,6 +1045,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
+ drm_vblank_put(dev, pipe);
return 0;
}
}
@@ -1094,6 +1069,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
if (dev_priv->swaps_pending >= 100) {
DRM_DEBUG("Too many swaps queued\n");
+ drm_vblank_put(dev, pipe);
return -EBUSY;
}
@@ -1101,17 +1077,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
if (!vbl_swap) {
DRM_ERROR("Failed to allocate memory to queue swap\n");
+ drm_vblank_put(dev, pipe);
return -ENOMEM;
}
DRM_DEBUG("\n");
- ret = drm_vblank_get(dev, pipe);
- if (ret) {
- drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
- return ret;
- }
-
vbl_swap->drw_id = swap->drawable;
vbl_swap->plane = plane;
vbl_swap->sequence = swap->sequence;
@@ -1135,83 +1106,15 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
*/
void i915_driver_irq_preinstall(struct drm_device * dev)
{
- struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- u32 tmp;
-
- tmp = I915_READ(PIPEASTAT);
- I915_WRITE(PIPEASTAT, tmp);
- tmp = I915_READ(PIPEBSTAT);
- I915_WRITE(PIPEBSTAT, tmp);
-
- atomic_set(&dev_priv->irq_received, 0);
- I915_WRITE(HWSTAM, 0xffff);
- I915_WRITE(IER, 0x0);
- I915_WRITE(IMR, 0xffffffff);
- I915_WRITE(IIR, 0xffffffff);
- (void) I915_READ(IIR);
+ return;
}
int i915_driver_irq_postinstall(struct drm_device * dev)
{
- struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- int ret, num_pipes = 2;
-
- DRM_SPININIT(&dev_priv->swaps_lock, "swap");
- INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
- dev_priv->swaps_pending = 0;
-
- DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
- dev_priv->user_irq_refcount = 0;
- dev_priv->irq_mask_reg = ~0;
-
- ret = drm_vblank_init(dev, num_pipes);
- if (ret)
- return ret;
-
- ret = drm_hotplug_init(dev);
- if (ret)
- return ret;
-
- dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-
- i915_enable_interrupt(dev);
- DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
-
- /*
- * Initialize the hardware status page IRQ location.
- */
-
- I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
return 0;
}
void i915_driver_irq_uninstall(struct drm_device * dev)
{
- struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
- u32 temp;
-
- if (!dev_priv)
- return;
-
- dev_priv->irq_enabled = 1;
-
- temp = I915_READ(PIPEASTAT);
- I915_WRITE(PIPEASTAT, temp);
- temp = I915_READ(PIPEBSTAT);
- I915_WRITE(PIPEBSTAT, temp);
- if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
- I915_WRITE(HWSTAM, 0xffffffff);
- I915_WRITE(IMR, 0xffffffff);
- I915_WRITE(IER, 0x0);
-
- temp = I915_READ(IIR);
- I915_WRITE(IIR, temp);
- } else {
- I915_WRITE16(HWSTAM, 0xffff);
- I915_WRITE16(IMR, 0xffff);
- I915_WRITE16(IER, 0x0);
-
- temp = I915_READ16(IIR);
- I915_WRITE16(IIR, temp);
- }
+ return;
}
diff --git a/shared-core/i915_suspend.c b/shared-core/i915_suspend.c
new file mode 100644
index 00000000..5e759b15
--- /dev/null
+++ b/shared-core/i915_suspend.c
@@ -0,0 +1,520 @@
+/* i915_suspend.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
+ */
+/*
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (pipe == PIPE_A)
+ return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
+ else
+ return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ u32 *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = dev_priv->save_palette_a;
+ else
+ array = dev_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ array[i] = I915_READ(reg + (i << 2));
+}
+
+static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ u32 *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = dev_priv->save_palette_a;
+ else
+ array = dev_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ I915_WRITE(reg + (i << 2), array[i]);
+}
+
+static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE8(index_port, reg);
+ return I915_READ8(data_port);
+}
+
+static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+ return I915_READ8(VGA_AR_DATA_READ);
+}
+
+static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+ I915_WRITE8(VGA_AR_DATA_WRITE, val);
+}
+
+static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE8(index_port, reg);
+ I915_WRITE8(data_port, val);
+}
+
+static void i915_save_vga(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+ u16 cr_index, cr_data, st01;
+
+ /* VGA color palette registers */
+ dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
+ /* DACCRX automatically increments during read */
+ I915_WRITE8(VGA_DACRX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
+
+ /* MSR bits */
+ dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
+ if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* CRT controller regs */
+ i915_write_indexed(dev, cr_index, cr_data, 0x11,
+ i915_read_indexed(dev, cr_index, cr_data, 0x11) &
+ (~0x80));
+ for (i = 0; i <= 0x24; i++)
+ dev_priv->saveCR[i] =
+ i915_read_indexed(dev, cr_index, cr_data, i);
+ /* Make sure we don't turn off CR group 0 writes */
+ dev_priv->saveCR[0x11] &= ~0x80;
+
+ /* Attribute controller registers */
+ I915_READ8(st01);
+ dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
+ for (i = 0; i <= 0x14; i++)
+ dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
+ I915_READ8(st01);
+ I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
+ I915_READ8(st01);
+
+ /* Graphics controller registers */
+ for (i = 0; i < 9; i++)
+ dev_priv->saveGR[i] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
+
+ dev_priv->saveGR[0x10] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+ dev_priv->saveGR[0x11] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+ dev_priv->saveGR[0x18] =
+ i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+ /* Sequencer registers */
+ for (i = 0; i < 8; i++)
+ dev_priv->saveSR[i] =
+ i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void i915_restore_vga(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+ u16 cr_index, cr_data, st01;
+
+ /* MSR bits */
+ I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
+ if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* Sequencer registers, don't write SR07 */
+ for (i = 0; i < 7; i++)
+ i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
+ dev_priv->saveSR[i]);
+
+ /* CRT controller regs */
+ /* Enable CR group 0 writes */
+ i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+ for (i = 0; i <= 0x24; i++)
+ i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
+
+ /* Graphics controller regs */
+ for (i = 0; i < 9; i++)
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
+ dev_priv->saveGR[i]);
+
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+ dev_priv->saveGR[0x10]);
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+ dev_priv->saveGR[0x11]);
+ i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+ dev_priv->saveGR[0x18]);
+
+ /* Attribute controller registers */
+ I915_READ8(st01); /* switch back to index mode */
+ for (i = 0; i <= 0x14; i++)
+ i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
+ I915_READ8(st01); /* switch back to index mode */
+ I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
+ I915_READ8(st01);
+
+ /* VGA color palette registers */
+ I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
+ /* DACCRX automatically increments during read */
+ I915_WRITE8(VGA_DACWX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
+
+}
+
+int i915_save_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+#if defined(__FreeBSD__)
+ dev_priv->saveLBB = (u8) pci_read_config(dev->device, LBB, 1);
+#else
+ pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+#endif
+
+ /* Display arbitration control */
+ dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+ /* Pipe & plane A info */
+ dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+ dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+ dev_priv->saveFPA0 = I915_READ(FPA0);
+ dev_priv->saveFPA1 = I915_READ(FPA1);
+ dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+ if (IS_I965G(dev))
+ dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+ dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+ dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+ dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+ dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+ dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+ dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+ dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+ dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+ dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+ dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+ dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+ dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+ if (IS_I965G(dev)) {
+ dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+ dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+ }
+ i915_save_palette(dev, PIPE_A);
+ dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+
+ /* Pipe & plane B info */
+ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+ dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+ dev_priv->saveFPB0 = I915_READ(FPB0);
+ dev_priv->saveFPB1 = I915_READ(FPB1);
+ dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+ if (IS_I965G(dev))
+ dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+ dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+ dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+ dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+ dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+ dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+ dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+ dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+ dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+ dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+ dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+ dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+ dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+ if (IS_I965GM(dev) || IS_GM45(dev)) {
+ dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+ dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+ }
+ i915_save_palette(dev, PIPE_B);
+ dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+
+ /* CRT state */
+ dev_priv->saveADPA = I915_READ(ADPA);
+
+ /* LVDS state */
+ dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+ dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+ if (IS_I965G(dev))
+ dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ dev_priv->saveLVDS = I915_READ(LVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+ dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+ dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+ dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+
+ /* FIXME: save TV & SDVO state */
+
+ /* FBC state */
+ dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+ dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+ dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+ dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+
+ /* Interrupt state */
+ dev_priv->saveIIR = I915_READ(IIR);
+ dev_priv->saveIER = I915_READ(IER);
+ dev_priv->saveIMR = I915_READ(IMR);
+
+ /* VGA state */
+ dev_priv->saveVGA0 = I915_READ(VGA0);
+ dev_priv->saveVGA1 = I915_READ(VGA1);
+ dev_priv->saveVGA_PD = I915_READ(VGA_PD);
+ dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+ /* Clock gating state */
+ dev_priv->saveD_STATE = I915_READ(D_STATE);
+ dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
+
+ /* Cache mode state */
+ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+
+ /* Memory Arbitration state */
+ dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+
+ /* Scratch space */
+ for (i = 0; i < 16; i++) {
+ dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
+ dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+
+ i915_save_vga(dev);
+
+ return 0;
+}
+
+int i915_restore_state(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+#if defined(__FreeBSD__)
+ pci_write_config(dev->device, LBB, dev_priv->saveLBB, 1);
+#else
+ pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+#endif
+
+ I915_WRITE(DSPARB, dev_priv->saveDSPARB);
+
+ /* Pipe & plane A info */
+ /* Prime the clock */
+ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+ I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+ ~DPLL_VCO_ENABLE);
+ DRM_UDELAY(150);
+ }
+ I915_WRITE(FPA0, dev_priv->saveFPA0);
+ I915_WRITE(FPA1, dev_priv->saveFPA1);
+ /* Actually enable it */
+ I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+ DRM_UDELAY(150);
+ if (IS_I965G(dev))
+ I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+ DRM_UDELAY(150);
+
+ /* Restore mode */
+ I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+ I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+ I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+ I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+ I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+ I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+ I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+ /* Restore plane info */
+ I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+ I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+ I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+ I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+ I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+ if (IS_I965G(dev)) {
+ I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+ I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+ }
+
+ I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+ i915_restore_palette(dev, PIPE_A);
+ /* Enable the plane */
+ I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+ I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+ /* Pipe & plane B info */
+ if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+ I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+ ~DPLL_VCO_ENABLE);
+ DRM_UDELAY(150);
+ }
+ I915_WRITE(FPB0, dev_priv->saveFPB0);
+ I915_WRITE(FPB1, dev_priv->saveFPB1);
+ /* Actually enable it */
+ I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+ DRM_UDELAY(150);
+ if (IS_I965G(dev))
+ I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+ DRM_UDELAY(150);
+
+ /* Restore mode */
+ I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+ I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+ I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+ I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+ I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+ I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+ I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+ /* Restore plane info */
+ I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+ I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+ I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+ I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+ I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+ if (IS_I965G(dev)) {
+ I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+ I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+ }
+
+ I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+ i915_restore_palette(dev, PIPE_B);
+ /* Enable the plane */
+ I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+ I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+
+ /* CRT state */
+ I915_WRITE(ADPA, dev_priv->saveADPA);
+
+ /* LVDS state */
+ if (IS_I965G(dev))
+ I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ I915_WRITE(LVDS, dev_priv->saveLVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+ I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+ I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+ I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+ I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+ I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
+ I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+
+ /* FIXME: restore TV & SDVO state */
+
+ /* FBC info */
+ I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+ I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+ I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+ I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+
+ /* VGA state */
+ I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+ I915_WRITE(VGA0, dev_priv->saveVGA0);
+ I915_WRITE(VGA1, dev_priv->saveVGA1);
+ I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
+ DRM_UDELAY(150);
+
+ /* Clock gating state */
+ I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+ I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
+
+ /* Cache mode state */
+ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+ /* Memory arbitration state */
+ I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+
+ for (i = 0; i < 16; i++) {
+ I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
+ I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+
+ i915_restore_vga(dev);
+
+ return 0;
+}
+
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 085336af..5ec2bc3e 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -131,7 +131,7 @@ int nouveau_fifo_init(struct drm_device *dev)
/* No cmdbuf object */
NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, 0x00000000);
NV_WRITE(NV03_PFIFO_CACHE0_PUSH0, 0x00000000);
- NV_WRITE(NV03_PFIFO_CACHE0_PULL0, 0x00000000);
+ NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x00000000);
NV_WRITE(NV04_PFIFO_SIZE, 0x0000FFFF);
NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF);
NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001);
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index 375463b4..1078a9c5 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -36,7 +36,6 @@
#include "nouveau_drv.h"
#include "nv50_kms_wrapper.h"
-
static struct mem_block *
split_block(struct mem_block *p, uint64_t start, uint64_t size,
struct drm_file *file_priv)
diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c
index 230c8e72..88186fe3 100644
--- a/shared-core/nv04_fifo.c
+++ b/shared-core/nv04_fifo.c
@@ -122,8 +122,8 @@ nv04_fifo_save_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t tmp;
- RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT);
- RAMFC_WR(DMA_GET, NV04_PFIFO_CACHE1_DMA_GET);
+ RAMFC_WR(DMA_PUT, NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+ RAMFC_WR(DMA_GET, NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
tmp |= NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE);
diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c
index e8f18dbc..05a76ef1 100644
--- a/shared-core/r300_cmdbuf.c
+++ b/shared-core/r300_cmdbuf.c
@@ -77,6 +77,9 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
return -EFAULT;
}
+ box.x2--; /* Hardware expects inclusive bottom-right corner */
+ box.y2--;
+
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
box.x1 = (box.x1) &
R300_CLIPRECT_MASK;
@@ -95,8 +98,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
R300_CLIPRECT_MASK;
box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
R300_CLIPRECT_MASK;
-
}
+
OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
(box.y1 << R300_CLIPRECT_Y_SHIFT));
OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
@@ -136,6 +139,18 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
ADVANCE_RING();
}
+ /* flus cache and wait idle clean after cliprect change */
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_DC_FLUSH);
+ ADVANCE_RING();
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+ ADVANCE_RING();
+ /* set flush flag */
+ dev_priv->track_flush |= RADEON_FLUSH_EMITED;
+
return 0;
}
@@ -166,13 +181,13 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(0x21DC, 1);
ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
ADD_RANGE(R300_VAP_CLIP_X_0, 4);
- ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+ ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
ADD_RANGE(R300_GB_ENABLE, 1);
ADD_RANGE(R300_GB_MSPOS0, 5);
- ADD_RANGE(R300_TX_CNTL, 1);
+ ADD_RANGE(R300_TX_INVALTAGS, 1);
ADD_RANGE(R300_TX_ENABLE, 1);
ADD_RANGE(0x4200, 4);
ADD_RANGE(0x4214, 1);
@@ -190,7 +205,7 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(0x42C0, 2);
ADD_RANGE(R300_RS_CNTL_0, 2);
- ADD_RANGE(0x43A4, 2);
+ ADD_RANGE(R300_SC_HYPERZ, 2);
ADD_RANGE(0x43E8, 1);
ADD_RANGE(0x46A4, 5);
@@ -209,14 +224,12 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(0x4E50, 9);
ADD_RANGE(0x4E88, 1);
ADD_RANGE(0x4EA0, 2);
- ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
- ADD_RANGE(R300_RB3D_ZSTENCIL_FORMAT, 4);
- ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
- ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
- ADD_RANGE(0x4F28, 1);
- ADD_RANGE(0x4F30, 2);
- ADD_RANGE(0x4F44, 1);
- ADD_RANGE(0x4F54, 1);
+ ADD_RANGE(R300_ZB_CNTL, 3);
+ ADD_RANGE(R300_ZB_FORMAT, 4);
+ ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
+ ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
+ ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
ADD_RANGE(R300_TX_FILTER_0, 16);
ADD_RANGE(R300_TX_FILTER1_0, 16);
@@ -229,7 +242,7 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
/* Sporadic registers used as primitives are emitted */
- ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
+ ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
@@ -243,6 +256,7 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(R500_RS_INST_0, 16);
ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
+ ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
} else {
ADD_RANGE(R300_PFS_CNTL_0, 3);
ADD_RANGE(R300_PFS_NODE_0, 4);
@@ -390,15 +404,28 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
if (sz * 16 > cmdbuf->bufsz)
return -EINVAL;
- BEGIN_RING(5 + sz * 4);
- /* Wait for VAP to come to senses.. */
- /* there is no need to emit it multiple times, (only once before VAP is programmed,
- but this optimization is for later */
- OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
+ /* VAP is very sensitive so we purge cache before we program it
+ * and we also flush its state before & after */
+ BEGIN_RING(6);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_DC_FLUSH);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+ OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
+ OUT_RING(0);
+ ADVANCE_RING();
+ /* set flush flag */
+ dev_priv->track_flush |= RADEON_FLUSH_EMITED;
+
+ BEGIN_RING(3 + sz * 4);
OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+ ADVANCE_RING();
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
+ OUT_RING(0);
ADVANCE_RING();
cmdbuf->buf += sz * 16;
@@ -426,6 +453,15 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
OUT_RING_TABLE((int *)cmdbuf->buf, 8);
ADVANCE_RING();
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_DC_FLUSH);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+ ADVANCE_RING();
+ /* set flush flag */
+ dev_priv->track_flush |= RADEON_FLUSH_EMITED;
+
cmdbuf->buf += 8 * 4;
cmdbuf->bufsz -= 8 * 4;
@@ -545,22 +581,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
return 0;
}
-static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
- drm_radeon_kcmd_buffer_t *cmdbuf)
+static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
- u32 *cmd = (u32 *) cmdbuf->buf;
- int count, ret;
+ u32 *cmd;
+ int count;
+ int expected_count;
RING_LOCALS;
- count=(cmd[0]>>16) & 0x3fff;
+ cmd = (u32 *) cmdbuf->buf;
+ count = (cmd[0]>>16) & 0x3fff;
+ expected_count = cmd[1] >> 16;
+ if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
+ expected_count = (expected_count+1)/2;
- if ((cmd[1] & 0x8000ffff) != 0x80000810) {
- DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
- return -EINVAL;
- }
- ret = !radeon_check_offset(dev_priv, cmd[2]);
- if (ret) {
- DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+ if (count && count != expected_count) {
+ DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
+ count, expected_count);
return -EINVAL;
}
@@ -572,6 +609,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
cmdbuf->buf += (count+2)*4;
cmdbuf->bufsz -= (count+2)*4;
+ if (!count) {
+ drm_r300_cmd_header_t header;
+
+ if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
+ DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
+ return -EINVAL;
+ }
+
+ header.u = *(unsigned int *)cmdbuf->buf;
+
+ cmdbuf->buf += sizeof(header);
+ cmdbuf->bufsz -= sizeof(header);
+ cmd = (u32 *) cmdbuf->buf;
+
+ if (header.header.cmd_type != R300_CMD_PACKET3 ||
+ header.packet3.packet != R300_CMD_PACKET3_RAW ||
+ cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
+ DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
+ return -EINVAL;
+ }
+
+ if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+ DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+ return -EINVAL;
+ }
+ if (!radeon_check_offset(dev_priv, cmd[2])) {
+ DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+ return -EINVAL;
+ }
+ if (cmd[3] != expected_count) {
+ DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
+ cmd[3], expected_count);
+ return -EINVAL;
+ }
+
+ BEGIN_RING(4);
+ OUT_RING(cmd[0]);
+ OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
+ ADVANCE_RING();
+
+ cmdbuf->buf += 4*4;
+ cmdbuf->bufsz -= 4*4;
+ }
+
return 0;
}
@@ -615,11 +696,22 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
case RADEON_CNTL_BITBLT_MULTI:
return r300_emit_bitblt_multi(dev_priv, cmdbuf);
- case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
- return r300_emit_indx_buffer(dev_priv, cmdbuf);
- case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
- case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
- case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
+ case RADEON_CP_INDX_BUFFER:
+ DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
+ return -EINVAL;
+ case RADEON_CP_3D_DRAW_IMMD_2:
+ /* triggers drawing using in-packet vertex data */
+ case RADEON_CP_3D_DRAW_VBUF_2:
+ /* triggers drawing of vertex buffers setup elsewhere */
+ dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
+ RADEON_PURGE_EMITED);
+ break;
+ case RADEON_CP_3D_DRAW_INDX_2:
+ /* triggers drawing using indices to vertex buffer */
+ /* whenever we send vertex we clear flush & purge */
+ dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
+ RADEON_PURGE_EMITED);
+ return r300_emit_draw_indx_2(dev_priv, cmdbuf);
case RADEON_WAIT_FOR_IDLE:
case RADEON_CP_NOP:
/* these packets are safe */
@@ -715,16 +807,53 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
*/
static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
{
+ uint32_t cache_z, cache_3d, cache_2d;
RING_LOCALS;
- BEGIN_RING(6);
+ cache_z = R300_ZC_FLUSH;
+ cache_2d = R300_DC_FLUSH_2D;
+ cache_3d = R300_DC_FLUSH_3D;
+ if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
+ /* we can purge, primitive where draw since last purge */
+ cache_z |= R300_ZC_FREE;
+ cache_2d |= R300_DC_FREE_2D;
+ cache_3d |= R300_DC_FREE_3D;
+ }
+
+ /* flush & purge zbuffer */
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
+ OUT_RING(cache_z);
+ ADVANCE_RING();
+ /* flush & purge 3d */
+ BEGIN_RING(2);
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
- OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
- OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
- OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
- OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
- OUT_RING(0x0);
+ OUT_RING(cache_3d);
+ ADVANCE_RING();
+ /* flush & purge texture */
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
+ OUT_RING(0);
+ ADVANCE_RING();
+ /* FIXME: is this one really needed ? */
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
+ OUT_RING(0);
+ ADVANCE_RING();
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+ ADVANCE_RING();
+ /* flush & purge 2d through E2 as RB2D will trigger lockup */
+ BEGIN_RING(4);
+ OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(cache_2d);
+ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
+ RADEON_WAIT_HOST_IDLECLEAN);
ADVANCE_RING();
+ /* set flush & purge flags */
+ dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
}
/**
@@ -906,8 +1035,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
DRM_DEBUG("\n");
- /* See the comment above r300_emit_begin3d for why this call must be here,
- * and what the cleanup gotos are for. */
+ /* pacify */
r300_pacify(dev_priv);
if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
diff --git a/shared-core/r300_reg.h b/shared-core/r300_reg.h
index 0be01fc7..d35dd39d 100644
--- a/shared-core/r300_reg.h
+++ b/shared-core/r300_reg.h
@@ -320,7 +320,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
* avoids bugs caused by still running shaders reading bad data from memory.
*/
-#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
+#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284
/* Absolutely no clue what this register is about. */
#define R300_VAP_UNKNOWN_2288 0x2288
@@ -516,7 +516,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* gap */
/* Zero to flush caches. */
-#define R300_TX_CNTL 0x4100
+#define R300_TX_INVALTAGS 0x4100
#define R300_TX_FLUSH 0x0
/* The upper enable bits are guessed, based on fglrx reported limits. */
@@ -705,6 +705,27 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11)
/* END: Rasterization / Interpolators - many guesses */
+/* Hierarchical Z Enable */
+#define R300_SC_HYPERZ 0x43a4
+# define R300_SC_HYPERZ_DISABLE (0 << 0)
+# define R300_SC_HYPERZ_ENABLE (1 << 0)
+# define R300_SC_HYPERZ_MIN (0 << 1)
+# define R300_SC_HYPERZ_MAX (1 << 1)
+# define R300_SC_HYPERZ_ADJ_256 (0 << 2)
+# define R300_SC_HYPERZ_ADJ_128 (1 << 2)
+# define R300_SC_HYPERZ_ADJ_64 (2 << 2)
+# define R300_SC_HYPERZ_ADJ_32 (3 << 2)
+# define R300_SC_HYPERZ_ADJ_16 (4 << 2)
+# define R300_SC_HYPERZ_ADJ_8 (5 << 2)
+# define R300_SC_HYPERZ_ADJ_4 (6 << 2)
+# define R300_SC_HYPERZ_ADJ_2 (7 << 2)
+# define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5)
+# define R300_SC_HYPERZ_HZ_Z0MIN (1 << 5)
+# define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6)
+# define R300_SC_HYPERZ_HZ_Z0MAX (1 << 6)
+
+#define R300_SC_EDGERULE 0x43a8
+
/* BEGIN: Scissors and cliprects */
/* There are four clipping rectangles. Their corner coordinates are inclusive.
@@ -1344,6 +1365,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
+#define R300_RB3D_AARESOLVE_CTL 0x4E88
/* gap */
/* Guess by Vladimir.
@@ -1358,19 +1380,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* for this.
* Bit (1<<8) is the "test" bit. so plain write is 6 - vd
*/
-#define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00
-# define R300_RB3D_Z_DISABLED_1 0x00000010
-# define R300_RB3D_Z_DISABLED_2 0x00000014
-# define R300_RB3D_Z_TEST 0x00000012
-# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
-# define R300_RB3D_Z_WRITE_ONLY 0x00000006
-
-# define R300_RB3D_Z_TEST 0x00000012
-# define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
-# define R300_RB3D_Z_WRITE_ONLY 0x00000006
-# define R300_RB3D_STENCIL_ENABLE 0x00000001
-
-#define R300_RB3D_ZSTENCIL_CNTL_1 0x4F04
+#define R300_ZB_CNTL 0x4F00
+# define R300_STENCIL_ENABLE (1 << 0)
+# define R300_Z_ENABLE (1 << 1)
+# define R300_Z_WRITE_ENABLE (1 << 2)
+# define R300_Z_SIGNED_COMPARE (1 << 3)
+# define R300_STENCIL_FRONT_BACK (1 << 4)
+
+#define R300_ZB_ZSTENCILCNTL 0x4f04
/* functions */
# define R300_ZS_NEVER 0
# define R300_ZS_LESS 1
@@ -1390,52 +1407,166 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_ZS_INVERT 5
# define R300_ZS_INCR_WRAP 6
# define R300_ZS_DECR_WRAP 7
+# define R300_Z_FUNC_SHIFT 0
/* front and back refer to operations done for front
and back faces, i.e. separate stencil function support */
-# define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT 0
-# define R300_RB3D_ZS1_FRONT_FUNC_SHIFT 3
-# define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT 6
-# define R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT 9
-# define R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT 12
-# define R300_RB3D_ZS1_BACK_FUNC_SHIFT 15
-# define R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT 18
-# define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT 21
-# define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT 24
-
-#define R300_RB3D_ZSTENCIL_CNTL_2 0x4F08
-# define R300_RB3D_ZS2_STENCIL_REF_SHIFT 0
-# define R300_RB3D_ZS2_STENCIL_MASK 0xFF
-# define R300_RB3D_ZS2_STENCIL_MASK_SHIFT 8
-# define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT 16
+# define R300_S_FRONT_FUNC_SHIFT 3
+# define R300_S_FRONT_SFAIL_OP_SHIFT 6
+# define R300_S_FRONT_ZPASS_OP_SHIFT 9
+# define R300_S_FRONT_ZFAIL_OP_SHIFT 12
+# define R300_S_BACK_FUNC_SHIFT 15
+# define R300_S_BACK_SFAIL_OP_SHIFT 18
+# define R300_S_BACK_ZPASS_OP_SHIFT 21
+# define R300_S_BACK_ZFAIL_OP_SHIFT 24
+
+#define R300_ZB_STENCILREFMASK 0x4f08
+# define R300_STENCILREF_SHIFT 0
+# define R300_STENCILREF_MASK 0x000000ff
+# define R300_STENCILMASK_SHIFT 8
+# define R300_STENCILMASK_MASK 0x0000ff00
+# define R300_STENCILWRITEMASK_SHIFT 16
+# define R300_STENCILWRITEMASK_MASK 0x00ff0000
/* gap */
-#define R300_RB3D_ZSTENCIL_FORMAT 0x4F10
-# define R300_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
-# define R300_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
- /* 16 bit format or some aditional bit ? */
-# define R300_DEPTH_FORMAT_UNK32 (32 << 0)
+#define R300_ZB_FORMAT 0x4f10
+# define R300_DEPTHFORMAT_16BIT_INT_Z (0 << 0)
+# define R300_DEPTHFORMAT_16BIT_13E3 (1 << 0)
+# define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL (2 << 0)
+/* reserved up to (15 << 0) */
+# define R300_INVERT_13E3_LEADING_ONES (0 << 4)
+# define R300_INVERT_13E3_LEADING_ZEROS (1 << 4)
-#define R300_RB3D_EARLY_Z 0x4F14
-# define R300_EARLY_Z_DISABLE (0 << 0)
-# define R300_EARLY_Z_ENABLE (1 << 0)
+#define R300_ZB_ZTOP 0x4F14
+# define R300_ZTOP_DISABLE (0 << 0)
+# define R300_ZTOP_ENABLE (1 << 0)
/* gap */
-#define R300_RB3D_ZCACHE_CTLSTAT 0x4F18 /* GUESS */
-# define R300_RB3D_ZCACHE_UNKNOWN_01 0x1
-# define R300_RB3D_ZCACHE_UNKNOWN_03 0x3
+#define R300_ZB_ZCACHE_CTLSTAT 0x4f18
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT (0 << 0)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT (0 << 1)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE (1 << 1)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE (0 << 31)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY (1 << 31)
+
+#define R300_ZB_BW_CNTL 0x4f1c
+# define R300_HIZ_DISABLE (0 << 0)
+# define R300_HIZ_ENABLE (1 << 0)
+# define R300_HIZ_MIN (0 << 1)
+# define R300_HIZ_MAX (1 << 1)
+# define R300_FAST_FILL_DISABLE (0 << 2)
+# define R300_FAST_FILL_ENABLE (1 << 2)
+# define R300_RD_COMP_DISABLE (0 << 3)
+# define R300_RD_COMP_ENABLE (1 << 3)
+# define R300_WR_COMP_DISABLE (0 << 4)
+# define R300_WR_COMP_ENABLE (1 << 4)
+# define R300_ZB_CB_CLEAR_RMW (0 << 5)
+# define R300_ZB_CB_CLEAR_CACHE_LINEAR (1 << 5)
+# define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE (0 << 6)
+# define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE (1 << 6)
+
+# define R500_ZEQUAL_OPTIMIZE_ENABLE (0 << 7)
+# define R500_ZEQUAL_OPTIMIZE_DISABLE (1 << 7)
+# define R500_SEQUAL_OPTIMIZE_ENABLE (0 << 8)
+# define R500_SEQUAL_OPTIMIZE_DISABLE (1 << 8)
+
+# define R500_BMASK_ENABLE (0 << 10)
+# define R500_BMASK_DISABLE (1 << 10)
+# define R500_HIZ_EQUAL_REJECT_DISABLE (0 << 11)
+# define R500_HIZ_EQUAL_REJECT_ENABLE (1 << 11)
+# define R500_HIZ_FP_EXP_BITS_DISABLE (0 << 12)
+# define R500_HIZ_FP_EXP_BITS_1 (1 << 12)
+# define R500_HIZ_FP_EXP_BITS_2 (2 << 12)
+# define R500_HIZ_FP_EXP_BITS_3 (3 << 12)
+# define R500_HIZ_FP_EXP_BITS_4 (4 << 12)
+# define R500_HIZ_FP_EXP_BITS_5 (5 << 12)
+# define R500_HIZ_FP_INVERT_LEADING_ONES (0 << 15)
+# define R500_HIZ_FP_INVERT_LEADING_ZEROS (1 << 15)
+# define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE (0 << 16)
+# define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE (1 << 16)
+# define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE (0 << 17)
+# define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE (1 << 17)
+# define R500_PEQ_PACKING_DISABLE (0 << 18)
+# define R500_PEQ_PACKING_ENABLE (1 << 18)
+# define R500_COVERED_PTR_MASKING_DISABLE (0 << 18)
+# define R500_COVERED_PTR_MASKING_ENABLE (1 << 18)
+
/* gap */
-#define R300_RB3D_DEPTHOFFSET 0x4F20
-#define R300_RB3D_DEPTHPITCH 0x4F24
-# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
-# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
-# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
-# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
-# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
-# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+/* Z Buffer Address Offset.
+ * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles.
+ */
+#define R300_ZB_DEPTHOFFSET 0x4f20
+
+/* Z Buffer Pitch and Endian Control */
+#define R300_ZB_DEPTHPITCH 0x4f24
+# define R300_DEPTHPITCH_MASK 0x00003FFC
+# define R300_DEPTHMACROTILE_DISABLE (0 << 16)
+# define R300_DEPTHMACROTILE_ENABLE (1 << 16)
+# define R300_DEPTHMICROTILE_LINEAR (0 << 17)
+# define R300_DEPTHMICROTILE_TILED (1 << 17)
+# define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+# define R300_DEPTHENDIAN_NO_SWAP (0 << 18)
+# define R300_DEPTHENDIAN_WORD_SWAP (1 << 18)
+# define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18)
+# define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
+
+/* Z Buffer Clear Value */
+#define R300_ZB_DEPTHCLEARVALUE 0x4f28
+
+#define R300_ZB_ZMASK_OFFSET 0x4f30
+#define R300_ZB_ZMASK_PITCH 0x4f34
+#define R300_ZB_ZMASK_WRINDEX 0x4f38
+#define R300_ZB_ZMASK_DWORD 0x4f3c
+#define R300_ZB_ZMASK_RDINDEX 0x4f40
+
+/* Hierarchical Z Memory Offset */
+#define R300_ZB_HIZ_OFFSET 0x4f44
+
+/* Hierarchical Z Write Index */
+#define R300_ZB_HIZ_WRINDEX 0x4f48
+
+/* Hierarchical Z Data */
+#define R300_ZB_HIZ_DWORD 0x4f4c
+
+/* Hierarchical Z Read Index */
+#define R300_ZB_HIZ_RDINDEX 0x4f50
+
+/* Hierarchical Z Pitch */
+#define R300_ZB_HIZ_PITCH 0x4f54
+
+/* Z Buffer Z Pass Counter Data */
+#define R300_ZB_ZPASS_DATA 0x4f58
+
+/* Z Buffer Z Pass Counter Address */
+#define R300_ZB_ZPASS_ADDR 0x4f5c
+
+/* Depth buffer X and Y coordinate offset */
+#define R300_ZB_DEPTHXY_OFFSET 0x4f60
+# define R300_DEPTHX_OFFSET_SHIFT 1
+# define R300_DEPTHX_OFFSET_MASK 0x000007FE
+# define R300_DEPTHY_OFFSET_SHIFT 17
+# define R300_DEPTHY_OFFSET_MASK 0x07FE0000
+
+/* Sets the fifo sizes */
+#define R500_ZB_FIFO_SIZE 0x4fd0
+# define R500_OP_FIFO_SIZE_FULL (0 << 0)
+# define R500_OP_FIFO_SIZE_HALF (1 << 0)
+# define R500_OP_FIFO_SIZE_QUATER (2 << 0)
+# define R500_OP_FIFO_SIZE_EIGTHS (4 << 0)
+
+/* Stencil Reference Value and Mask for backfacing quads */
+/* R300_ZB_STENCILREFMASK handles front face */
+#define R500_ZB_STENCILREFMASK_BF 0x4fd4
+# define R500_STENCILREF_SHIFT 0
+# define R500_STENCILREF_MASK 0x000000ff
+# define R500_STENCILMASK_SHIFT 8
+# define R500_STENCILMASK_MASK 0x0000ff00
+# define R500_STENCILWRITEMASK_SHIFT 16
+# define R500_STENCILWRITEMASK_MASK 0x00ff0000
/* BEGIN: Vertex program instruction set */
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 80951e91..6fbcfeab 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -40,6 +40,7 @@
#define RADEON_FIFO_DEBUG 0
static int radeon_do_cleanup_cp(struct drm_device * dev);
+static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
{
@@ -144,8 +145,12 @@ static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
+ } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+ RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
+ RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
} else {
- RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_base_lo);
+ RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
}
@@ -290,23 +295,8 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
DRM_UDELAY(1);
}
} else {
- /* 3D */
- tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT);
- tmp |= RADEON_RB3D_DC_FLUSH_ALL;
- RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp);
-
- /* 2D */
- tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
- tmp |= RADEON_RB3D_DC_FLUSH_ALL;
- RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
-
- for (i = 0; i < dev_priv->usec_timeout; i++) {
- if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
- & RADEON_RB3D_DC_BUSY)) {
- return 0;
- }
- DRM_UDELAY(1);
- }
+ /* don't flush or purge cache here or lockup */
+ return 0;
}
#if RADEON_FIFO_DEBUG
@@ -329,6 +319,9 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
return 0;
DRM_UDELAY(1);
}
+ DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
+ RADEON_READ(RADEON_RBBM_STATUS),
+ RADEON_READ(R300_VAP_CNTL_STATUS));
#if RADEON_FIFO_DEBUG
DRM_ERROR("failed!\n");
@@ -355,6 +348,9 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
}
DRM_UDELAY(1);
}
+ DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
+ RADEON_READ(RADEON_RBBM_STATUS),
+ RADEON_READ(R300_VAP_CNTL_STATUS));
#if RADEON_FIFO_DEBUG
DRM_ERROR("failed!\n");
@@ -448,6 +444,7 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
DRM_INFO("Loading R300 Microcode\n");
for (i = 0; i < 256; i++) {
@@ -536,14 +533,20 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
dev_priv->cp_running = 1;
- BEGIN_RING(6);
-
+ BEGIN_RING(8);
+ /* isync can only be written through cp on r5xx write it here */
+ OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
+ OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
+ RADEON_ISYNC_ANY3D_IDLE2D |
+ RADEON_ISYNC_WAIT_IDLEGUI |
+ RADEON_ISYNC_CPSCRATCH_IDLEGUI);
RADEON_PURGE_CACHE();
RADEON_PURGE_ZCACHE();
RADEON_WAIT_UNTIL_IDLE();
-
ADVANCE_RING();
COMMIT_RING();
+
+ dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
}
/* Reset the Command Processor. This will not flush any pending
@@ -858,14 +861,7 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
RS480_REQ_TYPE_SNOOP_DIS));
- if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
- IGP_WRITE_MCIND(RS690_MC_AGP_BASE,
- (unsigned int)dev_priv->gart_vm_start);
- IGP_WRITE_MCIND(RS690_MC_AGP_BASE_2, 0);
- } else {
- RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
- RADEON_WRITE(RS480_AGP_BASE_2, 0);
- }
+ radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
dev_priv->gart_size = 32*1024*1024;
temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
@@ -1064,7 +1060,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
(dev_priv->color_fmt << 10) |
(dev_priv->chip_family < CHIP_R200 ? RADEON_ZBLOCK16 : 0));
-
+
dev_priv->depth_clear.rb3d_zstencilcntl =
(dev_priv->depth_fmt |
RADEON_Z_TEST_ALWAYS |
@@ -1258,7 +1254,6 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
/* if we have an offset set from userspace */
if (dev_priv->pcigart_offset_set) {
-
/* if it came from userspace - remap it */
if (dev_priv->pcigart_offset_set == 1) {
dev_priv->gart_info.bus_addr =
@@ -1409,6 +1404,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
radeon_cp_init_ring_buffer(dev, dev_priv);
radeon_do_engine_reset(dev);
+ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
DRM_DEBUG("radeon_do_resume_cp() complete\n");
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index b8f49404..5ce97b64 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -39,7 +39,7 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
-#define DRIVER_DATE "20080528"
+#define DRIVER_DATE "20080613"
/* Interface history:
*
@@ -286,6 +286,9 @@ struct drm_radeon_master_private {
drm_radeon_sarea_t *sarea_priv;
};
+#define RADEON_FLUSH_EMITED (1 < 0)
+#define RADEON_PURGE_EMITED (1 < 1)
+
typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
@@ -360,7 +363,6 @@ typedef struct drm_radeon_private {
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
-
u32 scratch_ages[5];
unsigned int crtc_last_cnt;
@@ -370,12 +372,9 @@ typedef struct drm_radeon_private {
uint32_t flags; /* see radeon_chip_flags */
unsigned long fb_aper_offset;
- int num_gb_pipes;
-
struct radeon_mm_info mm;
drm_local_map_t *mmio;
- uint32_t chip_family;
unsigned long pcigart_offset;
unsigned int pcigart_offset_set;
@@ -393,6 +392,9 @@ typedef struct drm_radeon_private {
enum radeon_pll_errata pll_errata;
+ int num_gb_pipes;
+ int track_flush;
+ uint32_t chip_family; /* extract from flags */
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@@ -453,6 +455,7 @@ extern void radeon_mem_release(struct drm_file *file_priv,
struct mem_block *heap);
/* radeon_irq.c */
+extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state);
extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
@@ -746,11 +749,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_PP_TXFILTER_1 0x1c6c
#define RADEON_PP_TXFILTER_2 0x1c84
-#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c
-# define RADEON_RB2D_DC_FLUSH (3 << 0)
-# define RADEON_RB2D_DC_FREE (3 << 2)
-# define RADEON_RB2D_DC_FLUSH_ALL 0xf
-# define RADEON_RB2D_DC_BUSY (1 << 31)
#define RADEON_RB3D_CNTL 0x1c3c
# define RADEON_ALPHA_BLEND_ENABLE (1 << 0)
# define RADEON_PLANE_MASK_ENABLE (1 << 1)
@@ -776,9 +774,10 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define R300_ZB_ZCACHE_CTLSTAT 0x4f18
# define R300_ZC_FLUSH (1 << 0)
# define R300_ZC_FREE (1 << 1)
-# define R300_ZC_FLUSH_ALL 0x3
# define R300_ZC_BUSY (1 << 31)
#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c
+# define R300_RB3D_DC_FLUSH (2 << 0)
+# define R300_RB3D_DC_FREE (2 << 2)
# define R300_RB3D_DC_FINISH (1 << 4)
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
# define RADEON_Z_TEST_MASK (7 << 4)
@@ -1325,21 +1324,21 @@ do { \
#define RADEON_FLUSH_CACHE() do { \
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
- OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( RADEON_RB3D_DC_FLUSH ); \
+ OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(RADEON_RB3D_DC_FLUSH); \
} else { \
- OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( RADEON_RB3D_DC_FLUSH ); \
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(R300_RB3D_DC_FLUSH); \
} \
} while (0)
#define RADEON_PURGE_CACHE() do { \
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
- OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \
+ OUT_RING(CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \
} else { \
- OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \
+ OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE ); \
} \
} while (0)
@@ -1355,11 +1354,11 @@ do { \
#define RADEON_PURGE_ZCACHE() do { \
if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \
- OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
+ OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \
+ OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \
} else { \
- OUT_RING( CP_PACKET0( R300_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
- OUT_RING( R300_ZC_FLUSH_ALL ); \
+ OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \
+ OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \
} \
} while (0)
diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c
index f5f7f75d..dcf58e43 100644
--- a/shared-core/radeon_irq.c
+++ b/shared-core/radeon_irq.c
@@ -35,7 +35,7 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
-static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
+void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -255,35 +255,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- u32 crtc_cnt_reg, crtc_status_reg;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
+ if (crtc < 0 || crtc > 1) {
+ DRM_ERROR("Invalid crtc %d\n", crtc);
+ return -EINVAL;
+ }
+
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
- if (crtc == 0) {
- crtc_cnt_reg = R500_D1CRTC_FRAME_COUNT;
- crtc_status_reg = R500_D1CRTC_STATUS;
- } else if (crtc == 1) {
- crtc_cnt_reg = R500_D2CRTC_FRAME_COUNT;
- crtc_status_reg = R500_D2CRTC_STATUS;
- } else
- return -EINVAL;
- return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
-
+ if (crtc == 0)
+ return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
+ else
+ return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
} else {
- if (crtc == 0) {
- crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
- crtc_status_reg = RADEON_CRTC_STATUS;
- } else if (crtc == 1) {
- crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
- crtc_status_reg = RADEON_CRTC2_STATUS;
- } else {
- return -EINVAL;
- }
- return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
+ if (crtc == 0)
+ return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
+ else
+ return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
}
}
@@ -382,27 +374,8 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
int radeon_vblank_crtc_get(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
- u32 flag;
- u32 value;
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
- flag = RADEON_READ(R500_DxMODE_INT_MASK);
- value = 0;
- if (flag & R500_D1MODE_INT_MASK)
- value |= DRM_RADEON_VBLANK_CRTC1;
-
- if (flag & R500_D2MODE_INT_MASK)
- value |= DRM_RADEON_VBLANK_CRTC2;
- } else {
- flag = RADEON_READ(RADEON_GEN_INT_CNTL);
- value = 0;
- if (flag & RADEON_CRTC_VBLANK_MASK)
- value |= DRM_RADEON_VBLANK_CRTC1;
-
- if (flag & RADEON_CRTC2_VBLANK_MASK)
- value |= DRM_RADEON_VBLANK_CRTC2;
- }
- return value;
+ return dev_priv->vblank_crtc;
}
int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
diff --git a/shared-core/radeon_mem.c b/shared-core/radeon_mem.c
index 1e582ee0..dbd73c50 100644
--- a/shared-core/radeon_mem.c
+++ b/shared-core/radeon_mem.c
@@ -88,7 +88,7 @@ static struct mem_block *alloc_block(struct mem_block *heap, int size,
list_for_each(p, heap) {
int start = (p->start + mask) & ~mask;
- if (p->file_priv == 0 && start + size <= p->start + p->size)
+ if (p->file_priv == NULL && start + size <= p->start + p->size)
return split_block(p, start, size, file_priv);
}
@@ -113,7 +113,7 @@ static void free_block(struct mem_block *p)
/* Assumes a single contiguous range. Needs a special file_priv in
* 'heap' to stop it being subsumed.
*/
- if (p->next->file_priv == 0) {
+ if (p->next->file_priv == NULL) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
@@ -121,7 +121,7 @@ static void free_block(struct mem_block *p)
drm_free(q, sizeof(*q), DRM_MEM_BUFS);
}
- if (p->prev->file_priv == 0) {
+ if (p->prev->file_priv == NULL) {
struct mem_block *q = p->prev;
q->size += p->size;
q->next = p->next;
@@ -174,7 +174,7 @@ void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
* 'heap' to stop it being subsumed.
*/
list_for_each(p, heap) {
- while (p->file_priv == 0 && p->next->file_priv == 0) {
+ while (p->file_priv == NULL && p->next->file_priv == NULL) {
struct mem_block *q = p->next;
p->size += q->size;
p->next = q->next;
diff --git a/shared-core/xgi_drm.h b/shared-core/xgi_drm.h
index ce584420..7d01065e 100644
--- a/shared-core/xgi_drm.h
+++ b/shared-core/xgi_drm.h
@@ -123,11 +123,15 @@ struct xgi_state_info {
#define DRM_XGI_FREE 2
#define DRM_XGI_SUBMIT_CMDLIST 3
#define DRM_XGI_STATE_CHANGE 4
+#define DRM_XGI_SET_FENCE 5
+#define DRM_XGI_WAIT_FENCE 6
#define XGI_IOCTL_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_BOOTSTRAP, struct xgi_bootstrap)
#define XGI_IOCTL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_ALLOC, struct xgi_mem_alloc)
#define XGI_IOCTL_FREE DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_FREE, __u32)
#define XGI_IOCTL_SUBMIT_CMDLIST DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_SUBMIT_CMDLIST, struct xgi_cmd_info)
#define XGI_IOCTL_STATE_CHANGE DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_STATE_CHANGE, struct xgi_state_info)
+#define XGI_IOCTL_SET_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_SET_FENCE, u32)
+#define XGI_IOCTL_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_WAIT_FENCE, u32)
#endif /* _XGI_DRM_H_ */