]> err.no Git - linux-2.6/commitdiff
drm: SiS 315 Awareness.
authorThomas Hellstrom <thomas@tungstengraphics.com>
Tue, 8 Aug 2006 11:34:46 +0000 (21:34 +1000)
committerDave Airlie <airlied@linux.ie>
Thu, 21 Sep 2006 19:32:31 +0000 (05:32 +1000)
Add support for the SiS 315 to the DRM.

Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/char/drm/drm_pciids.h
drivers/char/drm/sis_drv.c
drivers/char/drm/sis_drv.h
drivers/char/drm/sis_mm.c

index bf9bdc50c1e3e5bdd42df0648691175f772506f6..8c16cde91133e7dae0faefa298f3364f59d9c707 100644 (file)
        {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}
 
index 93880e4492014079b19c8cb1c809fa7df0c286f9..3d5b3218b6ff02fa5da3e377276be76174692151 100644 (file)
@@ -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,
index 330a2c4eade2dec8bd35620c9423ef849a09a21d..2b8d6f6ed7c013adfb3affb0850a0c39e4276473 100644 (file)
 #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);
 
index 0eb1dca232b72565b66318fc02b4a0c3643d952f..3041c5b42d5684666cecb37840180695ebe13ed4 100644 (file)
@@ -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);
 }