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>
This commit is contained in:
parent
ceb9c27aa7
commit
cda1738066
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue