aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlia Mirkin <imirkin@alum.mit.edu>2014-01-19 04:18:15 -0500
committerBen Skeggs <bskeggs@redhat.com>2014-01-22 22:39:15 -0500
commitf87cd8b695d372087685976460fac1ec6ba2fca9 (patch)
tree8c46a2f23bc25618beb134bf3d7a11f0cf228e28
parentd5c1e84b3a130f0743b218b33ff7d9cb493ab5b4 (diff)
drm/nouveau/devinit: lock/unlock crtc regs for all devices, not just pre-nv50
Also make nv_lockvgac work for nv50+ devices. This should fix IO_CONDITION and related VBIOS opcodes that read/write the crtc regs. See https://bugs.freedesktop.org/show_bug.cgi?id=60680 Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/vga.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/base.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h8
4 files changed, 35 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
index 5a1c68474597..8836c3cb99c3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
@@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
138bool 138bool
139nv_lockvgac(void *obj, bool lock) 139nv_lockvgac(void *obj, bool lock)
140{ 140{
141 struct nouveau_device *dev = nv_device(obj);
142
141 bool locked = !nv_rdvgac(obj, 0, 0x1f); 143 bool locked = !nv_rdvgac(obj, 0, 0x1f);
142 u8 data = lock ? 0x99 : 0x57; 144 u8 data = lock ? 0x99 : 0x57;
143 nv_wrvgac(obj, 0, 0x1f, data); 145 if (dev->card_type < NV_50)
144 if (nv_device(obj)->chipset == 0x11) { 146 nv_wrvgac(obj, 0, 0x1f, data);
147 else
148 nv_wrvgac(obj, 0, 0x3f, data);
149 if (dev->chipset == 0x11) {
145 if (!(nv_rd32(obj, 0x001084) & 0x10000000)) 150 if (!(nv_rd32(obj, 0x001084) & 0x10000000))
146 nv_wrvgac(obj, 1, 0x1f, data); 151 nv_wrvgac(obj, 1, 0x1f, data);
147 } 152 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
index 6b23d9a0b953..8fa34e8152c2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
@@ -26,6 +26,7 @@
26 26
27#include <subdev/bios.h> 27#include <subdev/bios.h>
28#include <subdev/bios/init.h> 28#include <subdev/bios/init.h>
29#include <subdev/vga.h>
29 30
30#include "priv.h" 31#include "priv.h"
31 32
@@ -38,6 +39,9 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
38 if (suspend) 39 if (suspend)
39 devinit->post = true; 40 devinit->post = true;
40 41
42 /* unlock the extended vga crtc regs */
43 nv_lockvgac(devinit, false);
44
41 return nouveau_subdev_fini(&devinit->base, suspend); 45 return nouveau_subdev_fini(&devinit->base, suspend);
42} 46}
43 47
@@ -61,6 +65,17 @@ _nouveau_devinit_init(struct nouveau_object *object)
61 return 0; 65 return 0;
62} 66}
63 67
68void
69_nouveau_devinit_dtor(struct nouveau_object *object)
70{
71 struct nouveau_devinit *devinit = (void *)object;
72
73 /* lock crtc regs */
74 nv_lockvgac(devinit, true);
75
76 nouveau_subdev_destroy(&devinit->base);
77}
78
64int 79int
65nouveau_devinit_create_(struct nouveau_object *parent, 80nouveau_devinit_create_(struct nouveau_object *parent,
66 struct nouveau_object *engine, 81 struct nouveau_object *engine,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
index 24025e4e882a..7037eae46e44 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
@@ -388,17 +388,21 @@ int
388nv04_devinit_fini(struct nouveau_object *object, bool suspend) 388nv04_devinit_fini(struct nouveau_object *object, bool suspend)
389{ 389{
390 struct nv04_devinit_priv *priv = (void *)object; 390 struct nv04_devinit_priv *priv = (void *)object;
391 int ret;
391 392
392 /* make i2c busses accessible */ 393 /* make i2c busses accessible */
393 nv_mask(priv, 0x000200, 0x00000001, 0x00000001); 394 nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
394 395
395 /* unlock extended vga crtc regs, and unslave crtcs */ 396 ret = nouveau_devinit_fini(&priv->base, suspend);
396 nv_lockvgac(priv, false); 397 if (ret)
398 return ret;
399
400 /* unslave crtcs */
397 if (priv->owner < 0) 401 if (priv->owner < 0)
398 priv->owner = nv_rdvgaowner(priv); 402 priv->owner = nv_rdvgaowner(priv);
399 nv_wrvgaowner(priv, 0); 403 nv_wrvgaowner(priv, 0);
400 404
401 return nouveau_devinit_fini(&priv->base, suspend); 405 return 0;
402} 406}
403 407
404int 408int
@@ -426,9 +430,8 @@ nv04_devinit_dtor(struct nouveau_object *object)
426{ 430{
427 struct nv04_devinit_priv *priv = (void *)object; 431 struct nv04_devinit_priv *priv = (void *)object;
428 432
429 /* restore vga owner saved at first init, and lock crtc regs */ 433 /* restore vga owner saved at first init */
430 nv_wrvgaowner(priv, priv->owner); 434 nv_wrvgaowner(priv, priv->owner);
431 nv_lockvgac(priv, true);
432 435
433 nouveau_devinit_destroy(&priv->base); 436 nouveau_devinit_destroy(&priv->base);
434} 437}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
index c4179b6d6eca..822a2fbf44a5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
@@ -15,8 +15,10 @@ struct nouveau_devinit_impl {
15 15
16#define nouveau_devinit_create(p,e,o,d) \ 16#define nouveau_devinit_create(p,e,o,d) \
17 nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) 17 nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
18#define nouveau_devinit_destroy(p) \ 18#define nouveau_devinit_destroy(p) ({ \
19 nouveau_subdev_destroy(&(p)->base) 19 struct nouveau_devinit *d = (p); \
20 _nouveau_devinit_dtor(nv_object(d)); \
21})
20#define nouveau_devinit_init(p) ({ \ 22#define nouveau_devinit_init(p) ({ \
21 struct nouveau_devinit *d = (p); \ 23 struct nouveau_devinit *d = (p); \
22 _nouveau_devinit_init(nv_object(d)); \ 24 _nouveau_devinit_init(nv_object(d)); \
@@ -28,7 +30,7 @@ struct nouveau_devinit_impl {
28 30
29int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, 31int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
30 struct nouveau_oclass *, int, void **); 32 struct nouveau_oclass *, int, void **);
31#define _nouveau_devinit_dtor _nouveau_subdev_dtor 33void _nouveau_devinit_dtor(struct nouveau_object *);
32int _nouveau_devinit_init(struct nouveau_object *); 34int _nouveau_devinit_init(struct nouveau_object *);
33int _nouveau_devinit_fini(struct nouveau_object *, bool suspend); 35int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
34 36