From 1699aa9a127eefa2f568275189b44fc091cd2ff2 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 18 Oct 2013 23:09:01 -0400 Subject: [PATCH] drm/nouveau/agp: add a quirk list to limit agp modes Certain combinations of hardware can't actually support the maximum detected speed. Add a quirk list that lists pairs of hostbridge/chip pci ids and the mode that they should work with. Signed-off-by: Ilia Mirkin --- drivers/gpu/drm/nouveau/nouveau_agp.c | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c index 6e7a55f..b79e241 100644 --- a/drivers/gpu/drm/nouveau/nouveau_agp.c +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c @@ -11,10 +11,28 @@ MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); static int nouveau_agpmode = -1; module_param_named(agpmode, nouveau_agpmode, int, 0400); +struct nouveau_agpmode_quirk { + u16 hostbridge_vendor; + u16 hostbridge_device; + u16 chip_vendor; + u16 chip_device; + int mode; +}; + +static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = { + /* VIA KT133 / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */ + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, + + {}, +}; + static unsigned long -get_agp_mode(struct nouveau_drm *drm, unsigned long mode) +get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info) { struct nouveau_device *device = nv_device(drm->device); + struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list; + int agpmode = nouveau_agpmode; + unsigned long mode = info->mode; /* * FW seems to be broken on nv18, it makes the card lock up @@ -24,11 +42,27 @@ get_agp_mode(struct nouveau_drm *drm, unsigned long mode) mode &= ~PCI_AGP_COMMAND_FW; /* + * Go through the quirks list and adjust the agpmode accordingly. + */ + while (agpmode == -1 && quirk->hostbridge_vendor) { + if (info->id_vendor == quirk->hostbridge_vendor && + info->id_device == quirk->hostbridge_device && + device->pdev->vendor == quirk->chip_vendor && + device->pdev->device == quirk->chip_device) { + agpmode = quirk->mode; + nv_info(device, "Setting agp speed to %dX. Use agpmode to override.\n", + agpmode); + break; + } + ++quirk; + } + + /* * AGP mode set in the command line. */ - if (nouveau_agpmode > 0) { + if (agpmode > 0) { bool agpv3 = mode & 0x8; - int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; + int rate = agpv3 ? agpmode / 4 : agpmode; mode = (mode & ~0x7) | (rate & 0x7); } @@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm) if (ret) return; - mode.mode = get_agp_mode(drm, info.mode); + mode.mode = get_agp_mode(drm, &info); mode.mode &= ~PCI_AGP_COMMAND_FW; ret = drm_agp_enable(dev, mode); @@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm) } /* see agp.h for the AGPSTAT_* modes available */ - mode.mode = get_agp_mode(drm, info.mode); + mode.mode = get_agp_mode(drm, &info); ret = drm_agp_enable(dev, mode); if (ret) { -- 1.8.1.5