tree 374ad48818df951a03c59d54ec75d5b19d4a24c3
parent ceb9c27aa7d61c70f4c75f017d9fbc9de50034f1
author Dave Airlie <[EMAIL PROTECTED](none)> Sun, 10 Jul 2005 17:31:26 +1000
committer Dave Airlie <[EMAIL PROTECTED]> Sun, 10 Jul 2005 17:31:26 +1000

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 <[EMAIL PROTECTED]>

 drivers/char/drm/drmP.h     |   28 ++++++++++++++++++++++++++++
 drivers/char/drm/drm_stub.c |    3 ++-
 drivers/char/drm/i810_dma.c |   16 ++++++++++++++++
 drivers/char/drm/i810_drv.c |    1 +
 drivers/char/drm/i810_drv.h |    1 +
 drivers/char/drm/i830_dma.c |   16 ++++++++++++++++
 drivers/char/drm/i830_drv.c |    1 +
 drivers/char/drm/i830_drv.h |    1 +
 drivers/char/drm/i915_dma.c |   16 ++++++++++++++++
 drivers/char/drm/i915_drv.c |    1 +
 drivers/char/drm/i915_drv.h |    1 +
 drivers/char/drm/mga_drv.c  |   37 +++++++++++++++++++++++++++++++++++++
 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
--- 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_co
        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
--- 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 
                        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
--- 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
--- 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
--- 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
 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
--- 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
--- 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
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -137,6 +137,7 @@ extern void i830_driver_pretakedown(drm_
 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
--- 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
--- 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
--- 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
--- 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
--- 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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to