if (pmac_early_vresume_proc)
                pmac_early_vresume_proc(pmac_early_vresume_data);
 }
+
+/*
+ * AGP related suspend/resume code
+ */
+
+static struct pci_dev *pmac_agp_bridge __pmacdata;
+static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata;
+static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata;
+
+void __pmac pmac_register_agp_pm(struct pci_dev *bridge,
+                                int (*suspend)(struct pci_dev *bridge),
+                                int (*resume)(struct pci_dev *bridge))
+{
+       if (suspend || resume) {
+               pmac_agp_bridge = bridge;
+               pmac_agp_suspend = suspend;
+               pmac_agp_resume = resume;
+               return;
+       }
+       if (bridge != pmac_agp_bridge)
+               return;
+       pmac_agp_suspend = pmac_agp_resume = NULL;
+       return;
+}
+EXPORT_SYMBOL(pmac_register_agp_pm);
+
+void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev)
+{
+       if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
+               return;
+       if (pmac_agp_bridge->bus != dev->bus)
+               return;
+       pmac_agp_suspend(pmac_agp_bridge);
+}
+EXPORT_SYMBOL(pmac_suspend_agp_for_card);
+
+void __pmac pmac_resume_agp_for_card(struct pci_dev *dev)
+{
+       if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
+               return;
+       if (pmac_agp_bridge->bus != dev->bus)
+               return;
+       pmac_agp_resume(pmac_agp_bridge);
+}
+EXPORT_SYMBOL(pmac_resume_agp_for_card);
 
        dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
 #endif
 }
+
+/*
+ * Early video resume hook
+ */
+
+static void (*pmac_early_vresume_proc)(void *data) __pmacdata;
+static void *pmac_early_vresume_data __pmacdata;
+
+void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
+{
+       if (_machine != _MACH_Pmac)
+               return;
+       preempt_disable();
+       pmac_early_vresume_proc = proc;
+       pmac_early_vresume_data = data;
+       preempt_enable();
+}
+EXPORT_SYMBOL(pmac_set_early_video_resume);
+
+
+/*
+ * AGP related suspend/resume code
+ */
+
+static struct pci_dev *pmac_agp_bridge __pmacdata;
+static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata;
+static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata;
+
+void __pmac pmac_register_agp_pm(struct pci_dev *bridge,
+                                int (*suspend)(struct pci_dev *bridge),
+                                int (*resume)(struct pci_dev *bridge))
+{
+       if (suspend || resume) {
+               pmac_agp_bridge = bridge;
+               pmac_agp_suspend = suspend;
+               pmac_agp_resume = resume;
+               return;
+       }
+       if (bridge != pmac_agp_bridge)
+               return;
+       pmac_agp_suspend = pmac_agp_resume = NULL;
+       return;
+}
+EXPORT_SYMBOL(pmac_register_agp_pm);
+
+void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev)
+{
+       if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
+               return;
+       if (pmac_agp_bridge->bus != dev->bus)
+               return;
+       pmac_agp_suspend(pmac_agp_bridge);
+}
+EXPORT_SYMBOL(pmac_suspend_agp_for_card);
+
+void __pmac pmac_resume_agp_for_card(struct pci_dev *dev)
+{
+       if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
+               return;
+       if (pmac_agp_bridge->bus != dev->bus)
+               return;
+       pmac_agp_resume(pmac_agp_bridge);
+}
+EXPORT_SYMBOL(pmac_resume_agp_for_card);
 
 #include <asm/uninorth.h>
 #include <asm/pci-bridge.h>
 #include <asm/prom.h>
+#include <asm/pmac_feature.h>
 #include "agp.h"
 
 /*
 static int uninorth_rev;
 static int is_u3;
 
+
 static int uninorth_fetch_size(void)
 {
        int i;
                                       &scratch);
        } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
        if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
-               printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n");
+               printk(KERN_ERR PFX "failed to write UniNorth AGP"
+                      " command register\n");
 
        if (uninorth_rev >= 0x30) {
                /* This is an AGP V3 */
 }
 
 #ifdef CONFIG_PM
-static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state)
+/*
+ * These Power Management routines are _not_ called by the normal PCI PM layer,
+ * but directly by the video driver through function pointers in the device
+ * tree.
+ */
+static int agp_uninorth_suspend(struct pci_dev *pdev)
 {
+       struct agp_bridge_data *bridge;
        u32 cmd;
        u8 agp;
        struct pci_dev *device = NULL;
 
-       if (state != PMSG_SUSPEND)
+       bridge = agp_find_bridge(pdev);
+       if (bridge == NULL)
+               return -ENODEV;
+
+       /* Only one suspend supported */
+       if (bridge->dev_private_data)
                return 0;
 
        /* turn off AGP on the video chip, if it was enabled */
        /* turn off AGP on the bridge */
        agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
        pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+       bridge->dev_private_data = (void *)cmd;
        if (cmd & PCI_AGP_COMMAND_AGP) {
                printk("uninorth-agp: disabling AGP on bridge %s\n",
                                pci_name(pdev));
 
 static int agp_uninorth_resume(struct pci_dev *pdev)
 {
+       struct agp_bridge_data *bridge;
+       u32 command;
+
+       bridge = agp_find_bridge(pdev);
+       if (bridge == NULL)
+               return -ENODEV;
+
+       command = (u32)bridge->dev_private_data;
+       bridge->dev_private_data = NULL;
+       if (!(command & PCI_AGP_COMMAND_AGP))
+               return 0;
+
+       uninorth_agp_enable(bridge, command);
+
        return 0;
 }
-#endif
+#endif /* CONFIG_PM */
 
 static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
 {
                of_node_put(uninorth_node);
        }
 
+#ifdef CONFIG_PM
+       /* Inform platform of our suspend/resume caps */
+       pmac_register_agp_pm(pdev, agp_uninorth_suspend, agp_uninorth_resume);
+#endif
+
+       /* Allocate & setup our driver */
        bridge = agp_alloc_bridge();
        if (!bridge)
                return -ENOMEM;
 {
        struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
+#ifdef CONFIG_PM
+       /* Inform platform of our suspend/resume caps */
+       pmac_register_agp_pm(pdev, NULL, NULL);
+#endif
+
        agp_remove_bridge(bridge);
        agp_put_bridge(bridge);
 }
        .id_table       = agp_uninorth_pci_table,
        .probe          = agp_uninorth_probe,
        .remove         = agp_uninorth_remove,
-#ifdef CONFIG_PM
-       .suspend        = agp_uninorth_suspend,
-       .resume         = agp_uninorth_resume,
-#endif
 };
 
 static int __init agp_uninorth_init(void)
 
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct aty128fb_par *par = info->par;
-       u8 agp;
 
        /* We don't do anything but D2, for now we return 0, but
         * we may want to change that. How do we know if the BIOS
        par->asleep = 1;
        par->lock_blank = 1;
 
-       /* Disable AGP. The AGP host should have done it, but since ordering
-        * isn't always properly guaranteed in this specific case, let's make
-        * sure it's disabled on card side now. Ultimately, when merging fbdev
-        * and dri into some common infrastructure, this will be handled
-        * more nicely. The host bridge side will (or will not) be dealt with
-        * by the bridge AGP driver, we don't attempt to touch it here.
+#ifdef CONFIG_PPC_PMAC
+       /* On powermac, we have hooks to properly suspend/resume AGP now,
+        * use them here. We'll ultimately need some generic support here,
+        * but the generic code isn't quite ready for that yet
         */
-       agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
-       if (agp) {
-               u32 cmd;
-
-               pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
-               if (cmd & PCI_AGP_COMMAND_AGP) {
-                       printk(KERN_INFO "aty128fb: AGP was enabled, "
-                              "disabling ...\n");
-                       cmd &= ~PCI_AGP_COMMAND_AGP;
-                       pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
-                                              cmd);
-               }
-       }
+       pmac_suspend_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
 
        /* We need a way to make sure the fbdev layer will _not_ touch the
         * framebuffer before we put the chip to suspend state. On 2.4, I
        par->lock_blank = 0;
        aty128fb_blank(0, info);
 
+#ifdef CONFIG_PPC_PMAC
+       /* On powermac, we have hooks to properly suspend/resume AGP now,
+        * use them here. We'll ultimately need some generic support here,
+        * but the generic code isn't quite ready for that yet
+        */
+       pmac_resume_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
        pdev->dev.power.power_state = PMSG_ON;
 
        printk(KERN_DEBUG "aty128fb: resumed !\n");
 
 }
 
 
-static/*extern*/ int susdisking = 0;
-
 int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
-       u8 agp;
        int i;
 
        if (state == pdev->dev.power.power_state)
         */
        if (state != PM_SUSPEND_MEM)
                goto done;
-       if (susdisking) {
-               printk("radeonfb (%s): suspending to disk but state = %d\n",
-                      pci_name(pdev), state);
-               goto done;
-       }
 
        acquire_console_sem();
 
        rinfo->lock_blank = 1;
        del_timer_sync(&rinfo->lvds_timer);
 
-       /* Disable AGP. The AGP host should have done it, but since ordering
-        * isn't always properly guaranteed in this specific case, let's make
-        * sure it's disabled on card side now. Ultimately, when merging fbdev
-        * and dri into some common infrastructure, this will be handled
-        * more nicely. The host bridge side will (or will not) be dealt with
-        * by the bridge AGP driver, we don't attempt to touch it here.
+#ifdef CONFIG_PPC_PMAC
+       /* On powermac, we have hooks to properly suspend/resume AGP now,
+        * use them here. We'll ultimately need some generic support here,
+        * but the generic code isn't quite ready for that yet
         */
-       agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
-       if (agp) {
-               u32 cmd;
-
-               pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
-               if (cmd & PCI_AGP_COMMAND_AGP) {
-                       printk(KERN_INFO "radeonfb (%s): AGP was enabled, "
-                              "disabling ...\n",
-                              pci_name(pdev));
-                       cmd &= ~PCI_AGP_COMMAND_AGP;
-                       pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
-                                              cmd);
-               }
-       }
+       pmac_suspend_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
 
        /* If we support wakeup from poweroff, we save all regs we can including cfg
         * space
        rinfo->lock_blank = 0;
        radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
 
+#ifdef CONFIG_PPC_PMAC
+       /* On powermac, we have hooks to properly suspend/resume AGP now,
+        * use them here. We'll ultimately need some generic support here,
+        * but the generic code isn't quite ready for that yet
+        */
+       pmac_resume_agp_for_card(pdev);
+#endif /* CONFIG_PPC_PMAC */
+
+
        /* Check status of dynclk */
        if (rinfo->dynclk == 1)
                radeon_pm_enable_dynamic_mode(rinfo);
 
 
 #define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
 
+/* The AGP driver registers itself here */
+extern void pmac_register_agp_pm(struct pci_dev *bridge,
+                                int (*suspend)(struct pci_dev *bridge),
+                                int (*resume)(struct pci_dev *bridge));
+
+/* Those are meant to be used by video drivers to deal with AGP
+ * suspend resume properly
+ */
+extern void pmac_suspend_agp_for_card(struct pci_dev *dev);
+extern void pmac_resume_agp_for_card(struct pci_dev *dev);
+
 
 /*
  * The part below is for use by macio_asic.c only, do not rely