aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlia Mirkin <imirkin@alum.mit.edu>2013-10-27 11:54:09 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 00:39:54 -0500
commitfd34381b0e2827228cbda45aa2cca4127ff073b2 (patch)
tree731942ed4d819678d1993e8dfd3e075d2122fbd7
parente8d95b22b415bab6e411d6d0db82e26b4227762b (diff)
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. See https://bugs.freedesktop.org/show_bug.cgi?id=20341 Reported-by: Jason Detring <detringj@gmail.com> Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_agp.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c
index 6e7a55f93a85..2953c4e91e1a 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)");
11static int nouveau_agpmode = -1; 11static int nouveau_agpmode = -1;
12module_param_named(agpmode, nouveau_agpmode, int, 0400); 12module_param_named(agpmode, nouveau_agpmode, int, 0400);
13 13
14struct nouveau_agpmode_quirk {
15 u16 hostbridge_vendor;
16 u16 hostbridge_device;
17 u16 chip_vendor;
18 u16 chip_device;
19 int mode;
20};
21
22static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = {
23 /* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */
24 { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
25
26 {},
27};
28
14static unsigned long 29static unsigned long
15get_agp_mode(struct nouveau_drm *drm, unsigned long mode) 30get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
16{ 31{
17 struct nouveau_device *device = nv_device(drm->device); 32 struct nouveau_device *device = nv_device(drm->device);
33 struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list;
34 int agpmode = nouveau_agpmode;
35 unsigned long mode = info->mode;
18 36
19 /* 37 /*
20 * FW seems to be broken on nv18, it makes the card lock up 38 * 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)
24 mode &= ~PCI_AGP_COMMAND_FW; 42 mode &= ~PCI_AGP_COMMAND_FW;
25 43
26 /* 44 /*
45 * Go through the quirks list and adjust the agpmode accordingly.
46 */
47 while (agpmode == -1 && quirk->hostbridge_vendor) {
48 if (info->id_vendor == quirk->hostbridge_vendor &&
49 info->id_device == quirk->hostbridge_device &&
50 device->pdev->vendor == quirk->chip_vendor &&
51 device->pdev->device == quirk->chip_device) {
52 agpmode = quirk->mode;
53 nv_info(device, "Forcing agp mode to %dX. Use agpmode to override.\n",
54 agpmode);
55 break;
56 }
57 ++quirk;
58 }
59
60 /*
27 * AGP mode set in the command line. 61 * AGP mode set in the command line.
28 */ 62 */
29 if (nouveau_agpmode > 0) { 63 if (agpmode > 0) {
30 bool agpv3 = mode & 0x8; 64 bool agpv3 = mode & 0x8;
31 int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; 65 int rate = agpv3 ? agpmode / 4 : agpmode;
32 66
33 mode = (mode & ~0x7) | (rate & 0x7); 67 mode = (mode & ~0x7) | (rate & 0x7);
34 } 68 }
@@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm)
90 if (ret) 124 if (ret)
91 return; 125 return;
92 126
93 mode.mode = get_agp_mode(drm, info.mode); 127 mode.mode = get_agp_mode(drm, &info);
94 mode.mode &= ~PCI_AGP_COMMAND_FW; 128 mode.mode &= ~PCI_AGP_COMMAND_FW;
95 129
96 ret = drm_agp_enable(dev, mode); 130 ret = drm_agp_enable(dev, mode);
@@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm)
139 } 173 }
140 174
141 /* see agp.h for the AGPSTAT_* modes available */ 175 /* see agp.h for the AGPSTAT_* modes available */
142 mode.mode = get_agp_mode(drm, info.mode); 176 mode.mode = get_agp_mode(drm, &info);
143 177
144 ret = drm_agp_enable(dev, mode); 178 ret = drm_agp_enable(dev, mode);
145 if (ret) { 179 if (ret) {