diff options
author | Dave Airlie <airlied@starflyer.(none)> | 2005-07-10 17:31:26 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-07-10 17:31:26 +1000 |
commit | cda173806644d2af22ffd9896eed8ef99b97d356 (patch) | |
tree | 374ad48818df951a03c59d54ec75d5b19d4a24c3 /drivers/char | |
parent | ceb9c27aa7d61c70f4c75f017d9fbc9de50034f1 (diff) |
drm: add test for AGP devices and driver override for it.
Added device_is_agp callback to drm_driver. This function is called by the
platform-specific drm_device_is_agp function. Added implementation of this
function the the Linux-specific portion of the MGA driver to detect PCI G450
cards. Added code to the Linux-specific portion of the generic DRM layer to
not initialize AGP infrastructure if the card is not AGP (this matches what
already existed in BSD).
Fix up i810/i830 and i915 drivers to always return AGP as they don't always
report the capability.
Fix the MGA to not report AGP for a card that has an AGP chip behind a PCI
bridge.
From: Ian Romanick, Dave Airlie, Alan Hourihane
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/drm/drmP.h | 28 | ||||
-rw-r--r-- | drivers/char/drm/drm_stub.c | 3 | ||||
-rw-r--r-- | drivers/char/drm/i810_dma.c | 16 | ||||
-rw-r--r-- | drivers/char/drm/i810_drv.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/i810_drv.h | 1 | ||||
-rw-r--r-- | drivers/char/drm/i830_dma.c | 16 | ||||
-rw-r--r-- | drivers/char/drm/i830_drv.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/i830_drv.h | 1 | ||||
-rw-r--r-- | drivers/char/drm/i915_dma.c | 16 | ||||
-rw-r--r-- | drivers/char/drm/i915_drv.c | 1 | ||||
-rw-r--r-- | drivers/char/drm/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/char/drm/mga_drv.c | 37 | ||||
-rw-r--r-- | drivers/char/drm/mga_drv.h | 4 |
13 files changed, 123 insertions, 3 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 8e060a2cc3db..a9b61864feba 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -586,7 +586,22 @@ struct drm_driver { int (*kernel_context_switch)(struct drm_device *dev, int old, int new); void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); + + /** + * Called by \c drm_device_is_agp. Typically used to determine if a + * card is really attached to AGP or not. + * + * \param dev DRM device handle + * + * \returns + * One of three values is returned depending on whether or not the + * card is absolutely \b not AGP (return of 0), absolutely \b is AGP + * (return of 1), or may or may not be AGP (return of 2). + */ + int (*device_is_agp) (struct drm_device * dev); + /* these have to be filled in */ + int (*postinit)(struct drm_device *, unsigned long flags); irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); void (*irq_preinstall)(struct drm_device *dev); @@ -1041,6 +1056,19 @@ static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsig return NULL; } +static __inline__ int drm_device_is_agp(drm_device_t *dev) +{ + if ( dev->driver->device_is_agp != NULL ) { + int err = (*dev->driver->device_is_agp)( dev ); + + if (err != 2) { + return err; + } + } + + return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP); +} + static __inline__ void drm_core_dropmap(struct drm_map *map) { } diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 48829a1a086a..068ca9a8b0b4 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -91,7 +91,8 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct goto error_out_unreg; if (drm_core_has_AGP(dev)) { - dev->agp = drm_agp_init(dev); + if (drm_device_is_agp(dev)) + dev->agp = drm_agp_init(dev); if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { DRM_ERROR( "Cannot initialize the agpgart module.\n" ); retcode = -EINVAL; diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 18e0b7622893..0a9ac1f2e215 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -1383,3 +1383,19 @@ drm_ioctl_desc_t i810_ioctls[] = { }; int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); + +/** + * Determine if the device really is AGP or not. + * + * All Intel graphics chipsets are treated as AGP, even if they are really + * PCI-e. + * + * \param dev The device to be tested. + * + * \returns + * A value of 1 is always retured to indictate every i810 is AGP. + */ +int i810_driver_device_is_agp(drm_device_t * dev) +{ + return 1; +} diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index ff51b3259af9..00609329d578 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -84,6 +84,7 @@ static struct drm_driver driver = { .dev_priv_size = sizeof(drm_i810_buf_priv_t), .pretakedown = i810_driver_pretakedown, .prerelease = i810_driver_prerelease, + .device_is_agp = i810_driver_device_is_agp, .release = i810_driver_release, .dma_quiescent = i810_driver_dma_quiescent, .reclaim_buffers = i810_reclaim_buffers, diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index 1b40538d1725..62ee4f58c59a 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h @@ -120,6 +120,7 @@ extern int i810_driver_dma_quiescent(drm_device_t *dev); extern void i810_driver_release(drm_device_t *dev, struct file *filp); extern void i810_driver_pretakedown(drm_device_t *dev); extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp); +extern int i810_driver_device_is_agp(drm_device_t * dev); #define I810_BASE(reg) ((unsigned long) \ dev_priv->mmio_map->handle) diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index dc7733035864..80d8966397c1 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -1586,3 +1586,19 @@ drm_ioctl_desc_t i830_ioctls[] = { }; int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); + +/** + * Determine if the device really is AGP or not. + * + * All Intel graphics chipsets are treated as AGP, even if they are really + * PCI-e. + * + * \param dev The device to be tested. + * + * \returns + * A value of 1 is always retured to indictate every i8xx is AGP. + */ +int i830_driver_device_is_agp(drm_device_t * dev) +{ + return 1; +} diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c index bc36be76b8b2..0da9cd19919e 100644 --- a/drivers/char/drm/i830_drv.c +++ b/drivers/char/drm/i830_drv.c @@ -88,6 +88,7 @@ static struct drm_driver driver = { .dev_priv_size = sizeof(drm_i830_buf_priv_t), .pretakedown = i830_driver_pretakedown, .prerelease = i830_driver_prerelease, + .device_is_agp = i830_driver_device_is_agp, .release = i830_driver_release, .dma_quiescent = i830_driver_dma_quiescent, .reclaim_buffers = i830_reclaim_buffers, diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index df7746131dea..63f96a8b6a4a 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h @@ -137,6 +137,7 @@ extern void i830_driver_pretakedown(drm_device_t *dev); extern void i830_driver_release(drm_device_t *dev, struct file *filp); extern int i830_driver_dma_quiescent(drm_device_t *dev); extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp); +extern int i830_driver_device_is_agp(drm_device_t * dev); #define I830_BASE(reg) ((unsigned long) \ dev_priv->mmio_map->handle) diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 759f22943eb1..34f552f90c4a 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -732,3 +732,19 @@ drm_ioctl_desc_t i915_ioctls[] = { }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); + +/** + * Determine if the device really is AGP or not. + * + * All Intel graphics chipsets are treated as AGP, even if they are really + * PCI-e. + * + * \param dev The device to be tested. + * + * \returns + * A value of 1 is always retured to indictate every i9x5 is AGP. + */ +int i915_driver_device_is_agp(drm_device_t * dev) +{ + return 1; +} diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 1f59d3fc79bc..106b9ec02213 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c @@ -79,6 +79,7 @@ static struct drm_driver driver = { DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .pretakedown = i915_driver_pretakedown, .prerelease = i915_driver_prerelease, + .device_is_agp = i915_driver_device_is_agp, .irq_preinstall = i915_driver_irq_preinstall, .irq_postinstall = i915_driver_irq_postinstall, .irq_uninstall = i915_driver_irq_uninstall, diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 93080868d18f..70ed4e68eac8 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -103,6 +103,7 @@ typedef struct drm_i915_private { extern void i915_kernel_lost_context(drm_device_t * dev); extern void i915_driver_pretakedown(drm_device_t *dev); extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); +extern int i915_driver_device_is_agp(drm_device_t *dev); /* i915_irq.c */ extern int i915_irq_emit(DRM_IOCTL_ARGS); diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 844cca9cb29d..94af13bc66a4 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -38,6 +38,7 @@ #include "drm_pciids.h" +static int mga_driver_device_is_agp(drm_device_t * dev); static int postinit( struct drm_device *dev, unsigned long flags ) { dev->counters += 3; @@ -81,6 +82,7 @@ static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, .pretakedown = mga_driver_pretakedown, .dma_quiescent = mga_driver_dma_quiescent, + .device_is_agp = mga_driver_device_is_agp, .vblank_wait = mga_driver_vblank_wait, .irq_preinstall = mga_driver_irq_preinstall, .irq_postinstall = mga_driver_irq_postinstall, @@ -128,3 +130,38 @@ module_exit(mga_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL and additional rights"); + +/** + * Determine if the device really is AGP or not. + * + * In addition to the usual tests performed by \c drm_device_is_agp, this + * function detects PCI G450 cards that appear to the system exactly like + * AGP G450 cards. + * + * \param dev The device to be tested. + * + * \returns + * If the device is a PCI G450, zero is returned. Otherwise 2 is returned. + */ +int mga_driver_device_is_agp(drm_device_t * dev) +{ + const struct pci_dev * const pdev = dev->pdev; + + + /* There are PCI versions of the G450. These cards have the + * same PCI ID as the AGP G450, but have an additional PCI-to-PCI + * bridge chip. We detect these cards, which are not currently + * supported by this driver, by looking at the device ID of the + * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the + * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the + * device. + */ + + if ( (pdev->device == 0x0525) + && (pdev->bus->self->vendor == 0x3388) + && (pdev->bus->self->device == 0x0021) ) { + return 0; + } + + return 2; +} diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 9412e2816eb7..38f913905e04 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h @@ -38,11 +38,11 @@ #define DRIVER_NAME "mga" #define DRIVER_DESC "Matrox G200/G400" -#define DRIVER_DATE "20021029" +#define DRIVER_DATE "20051013" #define DRIVER_MAJOR 3 #define DRIVER_MINOR 1 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 1 typedef struct drm_mga_primary_buffer { u8 *start; |