aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/drm_pciids.h1
-rw-r--r--drivers/char/drm/sis_drv.c1
-rw-r--r--drivers/char/drm/sis_drv.h12
-rw-r--r--drivers/char/drm/sis_mm.c71
4 files changed, 84 insertions, 1 deletions
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index bf9bdc50c1e..8c16cde9113 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -209,6 +209,7 @@
{0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
{0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 93880e44920..3d5b3218b6f 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -69,6 +69,7 @@ static struct drm_driver driver = {
.load = sis_driver_load,
.unload = sis_driver_unload,
.context_dtor = NULL,
+ .dma_quiescent = sis_idle,
.reclaim_buffers = NULL,
.reclaim_buffers_locked = sis_reclaim_buffers_locked,
.lastclose = sis_lastclose,
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 330a2c4eade..2b8d6f6ed7c 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -34,13 +34,22 @@
#define DRIVER_AUTHOR "SIS, Tungsten Graphics"
#define DRIVER_NAME "sis"
#define DRIVER_DESC "SIS 300/630/540"
-#define DRIVER_DATE "20060529"
+#define DRIVER_DATE "20060704"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 2
#define DRIVER_PATCHLEVEL 1
+enum sis_family {
+ SIS_OTHER = 0,
+ SIS_CHIP_315 = 1,
+};
+
#include "drm_sman.h"
+#define SIS_BASE (dev_priv->mmio)
+#define SIS_READ(reg) DRM_READ32(SIS_BASE, reg);
+#define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val);
+
typedef struct drm_sis_private {
drm_local_map_t *mmio;
unsigned int idle_fault;
@@ -52,6 +61,7 @@ typedef struct drm_sis_private {
unsigned long agp_offset;
} drm_sis_private_t;
+extern int sis_idle(drm_device_t *dev);
extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
extern void sis_lastclose(drm_device_t *dev);
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 0eb1dca232b..3041c5b42d5 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -226,6 +226,76 @@ static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
return sis_drm_alloc(dev, priv, data, AGP_TYPE);
}
+static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+{
+ drm_map_list_t *entry;
+ drm_local_map_t *map;
+
+ list_for_each_entry(entry, &dev->maplist->head, head) {
+ map = entry->map;
+ if (!map)
+ continue;
+ if (map->type == _DRM_REGISTERS) {
+ return map;
+ }
+ }
+ return NULL;
+}
+
+int sis_idle(drm_device_t *dev)
+{
+ drm_sis_private_t *dev_priv = dev->dev_private;
+ uint32_t idle_reg;
+ unsigned long end;
+ int i;
+
+ if (dev_priv->idle_fault)
+ return 0;
+
+ if (dev_priv->mmio == NULL) {
+ dev_priv->mmio = sis_reg_init(dev);
+ if (dev_priv->mmio == NULL) {
+ DRM_ERROR("Could not find register map.\n");
+ return 0;
+ }
+ }
+
+ /*
+ * Implement a device switch here if needed
+ */
+
+ if (dev_priv->chipset != SIS_CHIP_315)
+ return 0;
+
+ /*
+ * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
+ * because its polling frequency is too low.
+ */
+
+ end = jiffies + (DRM_HZ * 3);
+
+ for (i=0; i<4; ++i) {
+ do {
+ idle_reg = SIS_READ(0x85cc);
+ } while ( !time_after_eq(jiffies, end) &&
+ ((idle_reg & 0x80000000) != 0x80000000));
+ }
+
+ if (time_after_eq(jiffies, end)) {
+ DRM_ERROR("Graphics engine idle timeout. "
+ "Disabling idle check\n");
+ dev_priv->idle_fault = TRUE;
+ }
+
+ /*
+ * The caller never sees an error code. It gets trapped
+ * in libdrm.
+ */
+
+ return 0;
+}
+
+
void sis_lastclose(struct drm_device *dev)
{
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -237,6 +307,7 @@ void sis_lastclose(struct drm_device *dev)
drm_sman_cleanup(&dev_priv->sman);
dev_priv->vram_initialized = FALSE;
dev_priv->agp_initialized = FALSE;
+ dev_priv->mmio = NULL;
mutex_unlock(&dev->struct_mutex);
}