From e04d8e829d7807e132d8c82c3554b164a803c617 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 23 Jul 2010 20:29:13 +0200 Subject: [PATCH] drm/nouveau: Reset AGP before running the init scripts. BIOS scripts usually make an attempt to reset the AGP controller, however on some nv4x cards doing it properly involves switching FW off and on: if we do that without updating the AGP bridge settings accordingly (e.g. with the corresponding calls to agp_enable()) we will be locking ourselves out of the card MMIO space. Do it from nouveau_mem_reset_agp() before the init scripts are executed. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 4 ++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_mem.c | 43 +++++++++++++++++++++++------------ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index e93fbcc..eeaf1f1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -259,6 +259,10 @@ nouveau_pci_resume(struct pci_dev *pdev) return -1; pci_set_master(dev->pdev); + /* Make sure the AGP controller is in a consistent state */ + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) + nouveau_mem_reset_agp(dev); + NV_INFO(dev, "POSTing device...\n"); ret = nouveau_run_vbios_init(dev); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9f4b8f2..8590032 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -688,6 +688,7 @@ extern int nouveau_card_init(struct drm_device *); extern int nouveau_mem_detect(struct drm_device *dev); extern int nouveau_mem_init(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *); +extern int nouveau_mem_reset_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 568bcc2..a9f36ab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -341,18 +341,36 @@ nouveau_mem_detect(struct drm_device *dev) return -ENOMEM; } -#if __OS_HAS_AGP -static void nouveau_mem_reset_agp(struct drm_device *dev) +int +nouveau_mem_reset_agp(struct drm_device *dev) { - uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable; +#if __OS_HAS_AGP + uint32_t saved_pci_nv_1, pmc_enable; + int ret; + + /* First of all, disable fast writes, otherwise if it's + * already enabled in the AGP bridge and we disable the card's + * AGP controller we might be locking ourselves out of it. */ + if (dev->agp->acquired) { + struct drm_agp_info info; + struct drm_agp_mode mode; + + ret = drm_agp_info(dev, &info); + if (ret) + return ret; + + mode.mode = info.mode & ~0x10; + ret = drm_agp_enable(dev, mode); + if (ret) + return ret; + } saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1); - saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19); /* clear busmaster bit */ nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); - /* clear SBA and AGP bits */ - nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); + /* disable AGP */ + nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0); /* power cycle pgraph, if enabled */ pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); @@ -364,11 +382,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev) } /* and restore (gives effect of resetting AGP) */ - nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19); nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1); -} #endif + return 0; +} + int nouveau_mem_init_agp(struct drm_device *dev) { @@ -378,11 +397,6 @@ nouveau_mem_init_agp(struct drm_device *dev) struct drm_agp_mode mode; int ret; - if (nouveau_noagp) - return 0; - - nouveau_mem_reset_agp(dev); - if (!dev->agp->acquired) { ret = drm_agp_acquire(dev); if (ret) { @@ -479,7 +493,8 @@ nouveau_mem_init(struct drm_device *dev) /* GART */ #if !defined(__powerpc__) && !defined(__ia64__) - if (drm_device_is_agp(dev) && dev->agp) { + if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { + nouveau_mem_reset_agp(dev); ret = nouveau_mem_init_agp(dev); if (ret) NV_ERROR(dev, "Error initialising AGP: %d\n", ret); -- 2.7.4