diff options
-rw-r--r-- | linux-core/sis_drv.c | 1 | ||||
-rw-r--r-- | linux-core/sis_mm.c | 72 | ||||
-rw-r--r-- | shared-core/drm_pciids.txt | 1 | ||||
-rw-r--r-- | shared-core/sis_drv.h | 16 |
4 files changed, 87 insertions, 3 deletions
diff --git a/linux-core/sis_drv.c b/linux-core/sis_drv.c index 4119bc3c..3fdbd88e 100644 --- a/linux-core/sis_drv.c +++ b/linux-core/sis_drv.c @@ -73,6 +73,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/linux-core/sis_mm.c b/linux-core/sis_mm.c index a89ed64b..70e2fac4 100644 --- a/linux-core/sis_mm.c +++ b/linux-core/sis_mm.c @@ -232,6 +232,77 @@ 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; @@ -243,6 +314,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; up(&dev->struct_sem); } diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index a86e4a24..e4415c16 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -201,6 +201,7 @@ 0x1039 0x0300 0 "SiS 300/305" 0x1039 0x5300 0 "SiS 540" 0x1039 0x6300 0 "SiS 630" +0x1039 0x6330 SIS_CHIP_315 "SiS 661" 0x1039 0x7300 0 "SiS 730" [tdfx] diff --git a/shared-core/sis_drv.h b/shared-core/sis_drv.h index 636e5327..ab3e9ae4 100644 --- a/shared-core/sis_drv.h +++ b/shared-core/sis_drv.h @@ -31,21 +31,30 @@ /* General customization: */ -#define DRIVER_AUTHOR "SIS" +#define DRIVER_AUTHOR "SIS, Tungsten Graphics" #define DRIVER_NAME "sis" #define DRIVER_DESC "SIS 300/630/540" -#define DRIVER_DATE "20060619" +#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, +}; + #if defined(__linux__) #define SIS_HAVE_CORE_MM #endif #ifdef SIS_HAVE_CORE_MM - #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 idle_fault; @@ -57,6 +66,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); |