aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_drm.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-07-11 10:44:20 +1000
committerBen Skeggs <bskeggs@redhat.com>2012-10-03 13:12:47 +1000
commitcb75d97e9c77743ecfcc43375be135a55a4d9b25 (patch)
treee7903f00db28b25a88d295dcc863f14b3d3bd707 /drivers/gpu/drm/nouveau/nouveau_drm.c
parent70790f4f819875e8f390871fd15bbbf823f28e1b (diff)
drm/nouveau: implement devinit subdev, and new init table parser
v2: - make sure not to execute display scripts unless resuming Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index c72d42636c8..3b4e65d5122 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -32,6 +32,7 @@
#include <subdev/device.h>
#include "nouveau_drm.h"
+#include "nouveau_agp.h"
int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *);
void nouveau_pci_remove(struct pci_dev *);
@@ -123,6 +124,30 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
INIT_LIST_HEAD(&drm->clients);
drm->dev = dev;
+ /* make sure AGP controller is in a consistent state before we
+ * (possibly) execute vbios init tables (see nouveau_agp.h)
+ */
+ if (drm_pci_device_is_agp(dev) && dev->agp) {
+ /* dummy device object, doesn't init anything, but allows
+ * agp code access to registers
+ */
+ ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT,
+ NVDRM_DEVICE, 0x0080,
+ &(struct nv_device_class) {
+ .device = ~0,
+ .disable =
+ ~(NV_DEVICE_DISABLE_MMIO |
+ NV_DEVICE_DISABLE_IDENTIFY),
+ .debug0 = ~0,
+ }, sizeof(struct nv_device_class),
+ &drm->device);
+ if (ret)
+ return ret;
+
+ nouveau_agp_reset(drm);
+ nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE);
+ }
+
ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE,
0x0080, &(struct nv_device_class) {
.device = ~0,
@@ -133,6 +158,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto fail_device;
+ /* initialise AGP */
+ nouveau_agp_init(drm);
+
ret = nouveau_load(dev, flags);
if (ret)
goto fail_device;
@@ -155,6 +183,8 @@ nouveau_drm_unload(struct drm_device *dev)
if (ret)
return ret;
+ nouveau_agp_fini(drm);
+
pci_set_drvdata(pdev, drm->client.base.device);
nouveau_cli_destroy(&drm->client);
return 0;
@@ -195,6 +225,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
if (ret)
goto fail_client;
+ nouveau_agp_fini(drm);
+
pci_save_state(pdev);
if (pm_state.event == PM_EVENT_SUSPEND) {
pci_disable_device(pdev);
@@ -230,12 +262,16 @@ nouveau_drm_resume(struct pci_dev *pdev)
return ret;
pci_set_master(pdev);
+ nouveau_agp_reset(drm);
+
nouveau_client_init(&drm->client.base);
list_for_each_entry(cli, &drm->clients, head) {
nouveau_client_init(&cli->base);
}
+ nouveau_agp_init(drm);
+
return nouveau_pci_resume(pdev);
}