diff options
author | Dave Airlie <airlied@starflyer.(none)> | 2005-07-10 03:31:26 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-07-10 03:31:26 -0400 |
commit | cda173806644d2af22ffd9896eed8ef99b97d356 (patch) | |
tree | 374ad48818df951a03c59d54ec75d5b19d4a24c3 | |
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>
-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 { | |||
586 | int (*kernel_context_switch)(struct drm_device *dev, int old, int new); | 586 | int (*kernel_context_switch)(struct drm_device *dev, int old, int new); |
587 | void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); | 587 | void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); |
588 | int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); | 588 | int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); |
589 | |||
590 | /** | ||
591 | * Called by \c drm_device_is_agp. Typically used to determine if a | ||
592 | * card is really attached to AGP or not. | ||
593 | * | ||
594 | * \param dev DRM device handle | ||
595 | * | ||
596 | * \returns | ||
597 | * One of three values is returned depending on whether or not the | ||
598 | * card is absolutely \b not AGP (return of 0), absolutely \b is AGP | ||
599 | * (return of 1), or may or may not be AGP (return of 2). | ||
600 | */ | ||
601 | int (*device_is_agp) (struct drm_device * dev); | ||
602 | |||
589 | /* these have to be filled in */ | 603 | /* these have to be filled in */ |
604 | |||
590 | int (*postinit)(struct drm_device *, unsigned long flags); | 605 | int (*postinit)(struct drm_device *, unsigned long flags); |
591 | irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); | 606 | irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); |
592 | void (*irq_preinstall)(struct drm_device *dev); | 607 | void (*irq_preinstall)(struct drm_device *dev); |
@@ -1041,6 +1056,19 @@ static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsig | |||
1041 | return NULL; | 1056 | return NULL; |
1042 | } | 1057 | } |
1043 | 1058 | ||
1059 | static __inline__ int drm_device_is_agp(drm_device_t *dev) | ||
1060 | { | ||
1061 | if ( dev->driver->device_is_agp != NULL ) { | ||
1062 | int err = (*dev->driver->device_is_agp)( dev ); | ||
1063 | |||
1064 | if (err != 2) { | ||
1065 | return err; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP); | ||
1070 | } | ||
1071 | |||
1044 | static __inline__ void drm_core_dropmap(struct drm_map *map) | 1072 | static __inline__ void drm_core_dropmap(struct drm_map *map) |
1045 | { | 1073 | { |
1046 | } | 1074 | } |
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 | |||
91 | goto error_out_unreg; | 91 | goto error_out_unreg; |
92 | 92 | ||
93 | if (drm_core_has_AGP(dev)) { | 93 | if (drm_core_has_AGP(dev)) { |
94 | dev->agp = drm_agp_init(dev); | 94 | if (drm_device_is_agp(dev)) |
95 | dev->agp = drm_agp_init(dev); | ||
95 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { | 96 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { |
96 | DRM_ERROR( "Cannot initialize the agpgart module.\n" ); | 97 | DRM_ERROR( "Cannot initialize the agpgart module.\n" ); |
97 | retcode = -EINVAL; | 98 | 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[] = { | |||
1383 | }; | 1383 | }; |
1384 | 1384 | ||
1385 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); | 1385 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); |
1386 | |||
1387 | /** | ||
1388 | * Determine if the device really is AGP or not. | ||
1389 | * | ||
1390 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
1391 | * PCI-e. | ||
1392 | * | ||
1393 | * \param dev The device to be tested. | ||
1394 | * | ||
1395 | * \returns | ||
1396 | * A value of 1 is always retured to indictate every i810 is AGP. | ||
1397 | */ | ||
1398 | int i810_driver_device_is_agp(drm_device_t * dev) | ||
1399 | { | ||
1400 | return 1; | ||
1401 | } | ||
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 = { | |||
84 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), | 84 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), |
85 | .pretakedown = i810_driver_pretakedown, | 85 | .pretakedown = i810_driver_pretakedown, |
86 | .prerelease = i810_driver_prerelease, | 86 | .prerelease = i810_driver_prerelease, |
87 | .device_is_agp = i810_driver_device_is_agp, | ||
87 | .release = i810_driver_release, | 88 | .release = i810_driver_release, |
88 | .dma_quiescent = i810_driver_dma_quiescent, | 89 | .dma_quiescent = i810_driver_dma_quiescent, |
89 | .reclaim_buffers = i810_reclaim_buffers, | 90 | .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); | |||
120 | extern void i810_driver_release(drm_device_t *dev, struct file *filp); | 120 | extern void i810_driver_release(drm_device_t *dev, struct file *filp); |
121 | extern void i810_driver_pretakedown(drm_device_t *dev); | 121 | extern void i810_driver_pretakedown(drm_device_t *dev); |
122 | extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 122 | extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
123 | extern int i810_driver_device_is_agp(drm_device_t * dev); | ||
123 | 124 | ||
124 | #define I810_BASE(reg) ((unsigned long) \ | 125 | #define I810_BASE(reg) ((unsigned long) \ |
125 | dev_priv->mmio_map->handle) | 126 | 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[] = { | |||
1586 | }; | 1586 | }; |
1587 | 1587 | ||
1588 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); | 1588 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); |
1589 | |||
1590 | /** | ||
1591 | * Determine if the device really is AGP or not. | ||
1592 | * | ||
1593 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
1594 | * PCI-e. | ||
1595 | * | ||
1596 | * \param dev The device to be tested. | ||
1597 | * | ||
1598 | * \returns | ||
1599 | * A value of 1 is always retured to indictate every i8xx is AGP. | ||
1600 | */ | ||
1601 | int i830_driver_device_is_agp(drm_device_t * dev) | ||
1602 | { | ||
1603 | return 1; | ||
1604 | } | ||
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 = { | |||
88 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), | 88 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), |
89 | .pretakedown = i830_driver_pretakedown, | 89 | .pretakedown = i830_driver_pretakedown, |
90 | .prerelease = i830_driver_prerelease, | 90 | .prerelease = i830_driver_prerelease, |
91 | .device_is_agp = i830_driver_device_is_agp, | ||
91 | .release = i830_driver_release, | 92 | .release = i830_driver_release, |
92 | .dma_quiescent = i830_driver_dma_quiescent, | 93 | .dma_quiescent = i830_driver_dma_quiescent, |
93 | .reclaim_buffers = i830_reclaim_buffers, | 94 | .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); | |||
137 | extern void i830_driver_release(drm_device_t *dev, struct file *filp); | 137 | extern void i830_driver_release(drm_device_t *dev, struct file *filp); |
138 | extern int i830_driver_dma_quiescent(drm_device_t *dev); | 138 | extern int i830_driver_dma_quiescent(drm_device_t *dev); |
139 | extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 139 | extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
140 | extern int i830_driver_device_is_agp(drm_device_t * dev); | ||
140 | 141 | ||
141 | #define I830_BASE(reg) ((unsigned long) \ | 142 | #define I830_BASE(reg) ((unsigned long) \ |
142 | dev_priv->mmio_map->handle) | 143 | 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[] = { | |||
732 | }; | 732 | }; |
733 | 733 | ||
734 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 734 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
735 | |||
736 | /** | ||
737 | * Determine if the device really is AGP or not. | ||
738 | * | ||
739 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
740 | * PCI-e. | ||
741 | * | ||
742 | * \param dev The device to be tested. | ||
743 | * | ||
744 | * \returns | ||
745 | * A value of 1 is always retured to indictate every i9x5 is AGP. | ||
746 | */ | ||
747 | int i915_driver_device_is_agp(drm_device_t * dev) | ||
748 | { | ||
749 | return 1; | ||
750 | } | ||
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 = { | |||
79 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, | 79 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, |
80 | .pretakedown = i915_driver_pretakedown, | 80 | .pretakedown = i915_driver_pretakedown, |
81 | .prerelease = i915_driver_prerelease, | 81 | .prerelease = i915_driver_prerelease, |
82 | .device_is_agp = i915_driver_device_is_agp, | ||
82 | .irq_preinstall = i915_driver_irq_preinstall, | 83 | .irq_preinstall = i915_driver_irq_preinstall, |
83 | .irq_postinstall = i915_driver_irq_postinstall, | 84 | .irq_postinstall = i915_driver_irq_postinstall, |
84 | .irq_uninstall = i915_driver_irq_uninstall, | 85 | .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 { | |||
103 | extern void i915_kernel_lost_context(drm_device_t * dev); | 103 | extern void i915_kernel_lost_context(drm_device_t * dev); |
104 | extern void i915_driver_pretakedown(drm_device_t *dev); | 104 | extern void i915_driver_pretakedown(drm_device_t *dev); |
105 | extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 105 | extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
106 | extern int i915_driver_device_is_agp(drm_device_t *dev); | ||
106 | 107 | ||
107 | /* i915_irq.c */ | 108 | /* i915_irq.c */ |
108 | extern int i915_irq_emit(DRM_IOCTL_ARGS); | 109 | 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 @@ | |||
38 | 38 | ||
39 | #include "drm_pciids.h" | 39 | #include "drm_pciids.h" |
40 | 40 | ||
41 | static int mga_driver_device_is_agp(drm_device_t * dev); | ||
41 | static int postinit( struct drm_device *dev, unsigned long flags ) | 42 | static int postinit( struct drm_device *dev, unsigned long flags ) |
42 | { | 43 | { |
43 | dev->counters += 3; | 44 | dev->counters += 3; |
@@ -81,6 +82,7 @@ static struct drm_driver driver = { | |||
81 | .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 82 | .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
82 | .pretakedown = mga_driver_pretakedown, | 83 | .pretakedown = mga_driver_pretakedown, |
83 | .dma_quiescent = mga_driver_dma_quiescent, | 84 | .dma_quiescent = mga_driver_dma_quiescent, |
85 | .device_is_agp = mga_driver_device_is_agp, | ||
84 | .vblank_wait = mga_driver_vblank_wait, | 86 | .vblank_wait = mga_driver_vblank_wait, |
85 | .irq_preinstall = mga_driver_irq_preinstall, | 87 | .irq_preinstall = mga_driver_irq_preinstall, |
86 | .irq_postinstall = mga_driver_irq_postinstall, | 88 | .irq_postinstall = mga_driver_irq_postinstall, |
@@ -128,3 +130,38 @@ module_exit(mga_exit); | |||
128 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 130 | MODULE_AUTHOR( DRIVER_AUTHOR ); |
129 | MODULE_DESCRIPTION( DRIVER_DESC ); | 131 | MODULE_DESCRIPTION( DRIVER_DESC ); |
130 | MODULE_LICENSE("GPL and additional rights"); | 132 | MODULE_LICENSE("GPL and additional rights"); |
133 | |||
134 | /** | ||
135 | * Determine if the device really is AGP or not. | ||
136 | * | ||
137 | * In addition to the usual tests performed by \c drm_device_is_agp, this | ||
138 | * function detects PCI G450 cards that appear to the system exactly like | ||
139 | * AGP G450 cards. | ||
140 | * | ||
141 | * \param dev The device to be tested. | ||
142 | * | ||
143 | * \returns | ||
144 | * If the device is a PCI G450, zero is returned. Otherwise 2 is returned. | ||
145 | */ | ||
146 | int mga_driver_device_is_agp(drm_device_t * dev) | ||
147 | { | ||
148 | const struct pci_dev * const pdev = dev->pdev; | ||
149 | |||
150 | |||
151 | /* There are PCI versions of the G450. These cards have the | ||
152 | * same PCI ID as the AGP G450, but have an additional PCI-to-PCI | ||
153 | * bridge chip. We detect these cards, which are not currently | ||
154 | * supported by this driver, by looking at the device ID of the | ||
155 | * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the | ||
156 | * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the | ||
157 | * device. | ||
158 | */ | ||
159 | |||
160 | if ( (pdev->device == 0x0525) | ||
161 | && (pdev->bus->self->vendor == 0x3388) | ||
162 | && (pdev->bus->self->device == 0x0021) ) { | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | return 2; | ||
167 | } | ||
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 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "mga" | 39 | #define DRIVER_NAME "mga" |
40 | #define DRIVER_DESC "Matrox G200/G400" | 40 | #define DRIVER_DESC "Matrox G200/G400" |
41 | #define DRIVER_DATE "20021029" | 41 | #define DRIVER_DATE "20051013" |
42 | 42 | ||
43 | #define DRIVER_MAJOR 3 | 43 | #define DRIVER_MAJOR 3 |
44 | #define DRIVER_MINOR 1 | 44 | #define DRIVER_MINOR 1 |
45 | #define DRIVER_PATCHLEVEL 0 | 45 | #define DRIVER_PATCHLEVEL 1 |
46 | 46 | ||
47 | typedef struct drm_mga_primary_buffer { | 47 | typedef struct drm_mga_primary_buffer { |
48 | u8 *start; | 48 | u8 *start; |