Merge to kernel-2.6.20-1.2949.fc6.vs2.2.0.1
[linux-2.6.git] / drivers / video / aty / radeon_pm.c
index 50af897..9a2b0d6 100644 (file)
 #include <linux/agp_backend.h>
 
 #ifdef CONFIG_PPC_PMAC
-#include <asm/processor.h>
+#include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/pmac_feature.h>
 #endif
 
-/* For detecting supported PC laptops */
-#ifdef CONFIG_X86
-#include <linux/dmi.h>
-#endif
-
 #include "ati_ids.h"
 
-#ifdef CONFIG_X86
-/* This array holds a list of supported PC laptops.
- * Currently only few IBM models are tested.
- * If you want to experiment, use dmidecode to find out
- * vendor and product codes for Your laptop.
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
+
+/*
+ * Workarounds for bugs in PC laptops:
+ * - enable D2 sleep in some IBM Thinkpads
+ * - special case for Samsung P35
+ *
+ * Whitelist by subsystem vendor/device because
+ * its the subsystem vendor's fault!
  */
-static struct dmi_system_id __devinitdata radeonfb_dmi_table[] = {
-       {
-               /* Reported by George Avrunin <avrunin@math.umass.edu> */
-               .ident = "IBM ThinkPad T40 (2372-9CU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23729CU"),
-               },
-       },
-       {
-               /* Reported by Pete Toscano <pete@verisignlabs.com> */
-               .ident = "IBM ThinkPad R40 (2722-B3G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2722B3G"),
-               },
-       },
-       {
-               /* Reported by Klaus Kurzmann <mok@fluxnetz.de> */
-               .ident = "IBM ThinkPad T40 (2373-25G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "237325G"),
-               },
-       },
-       {
-               /* Reported by Antti Andreimann <Antti.Andreimann@mail.ee> */
-               .ident = "IBM ThinkPad T41 (2373-2FG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23732FG"),
-               },
-       },
-       {
-               /* Reported by Antti P Miettinen <apm@brigitte.dna.fi> */
-               .ident = "IBM ThinkPad T40 (2373-4G2)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23734G2"),
-             },
-       },
-       {
-               /* Reported by Pete Toscano <pete@verisignlabs.com> */
-               .ident = "IBM ThinkPad T40 (2373-92G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "237392G"),
-             },
-       },
-       {
-               /* Reported by Pete Toscano <pete@verisignlabs.com> */
-               .ident = "IBM ThinkPad T40 (2373-8CG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23738CG"),
-               },
-       },
-       {
-               /* Reported by Pete Toscano <pete@verisignlabs.com> */
-               .ident = "IBM ThinkPad T40 (2373-94U)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "237394U"),
-               },
-       },
-       {
-               /* Reported by Manuel Carro <mcarro@fi.upm.es> */
-               .ident = "IBM ThinkPad T40 (2373-94G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "237394G"),
-               },
-       },
-       {
-               /* Reported by Peter Jones <pjones@redhat.com> */
-               .ident = "IBM ThinkPad T41 (2373-9FU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23739FU"),
-               },
-       },
-       {
-               /* Reported by Ajay Ramaswamy <ajay@ramaswamy.net> */
-               .ident = "IBM ThinkPad T41 (2373-9HU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23739HU"),
-             },
-       },
-       {
-               /* Reported by Peter Jones <pjones@redhat.com> */
-               .ident = "IBM ThinkPad T40 (2373-BU7)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373BU7"),
-               },
-       },
-       {
-               /* Reported by Jerome Poggi <Jerome.Poggi@hsc.fr> */
-               .ident = "IBM ThinkPad T42 (2373-FWG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373FWG"),
-               },
-       },
-       {
-               /* Reported by Juerg Billeter <j@bitron.ch> */
-               .ident = "IBM ThinkPad T40p (2373-G1G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373G1G"),
-               },
-       },
-       {
-               /* Reported by Hartwig, Thomas <t.hartwig@itth.com> */
-               .ident = "IBM ThinkPad T40p (2373-G3G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373G3G"),
-               },
-       },
-       {
-               /* Reported by Eric Benson <eric_a_benson@yahoo.com> */
-               .ident = "IBM ThinkPad T41p (2373-GEU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373GEU"),
-               },
-       },
-       {
-               /* Reported by Dwight Barkley <barkley@maths.warwick.ac.uk> */
-               .ident = "IBM ThinkPad T42 (2373-JTU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373JTU"),
-               },
-       },
-       {
-               /* Reported by Vernon Mauery <vernux@us.ibm.com> */
-               .ident = "IBM ThinkPad T40 (2373-MU4)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373MU4"),
-               },
-       },
-       {
-               /* Reported by Ajay Ramaswamy <ajay@ramaswamy.net> */
-               .ident = "IBM ThinkPad T41 (2373-XNX)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373XNX"),
-             },
-       },
-       {
-               /* Reported by obi <graziano@cs.ucsb.edu> */
-               .ident = "IBM ThinkPad T41 (2378-DEU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2378DEU"),
-               },
-       },
-       {
-               /* Reported by Volker Braun <vbraun@physics.upenn.edu> */
-               .ident = "IBM ThinkPad T41 (2379-DJU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2379DJU"),
-               },
-       },
-       {
-               /* Reported by Pete Toscano <pete@verisignlabs.com> */
-               .ident = "IBM ThinkPad T42 (2373-FWG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373FWG"),
-               },
-       },
-       {
-               /* Reported by Frank Schmitt <tonne2004@gehheimdienst.de> */
-               .ident = "IBM ThinkPad R40 (2722-3GG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "27223GG"),
-               },
-       },
-       {
-               /* Reported by Nils Trebing <nils.trebing@uni-konstanz.de> */
-               .ident = "IBM ThinkPad R40 (2722-5MG)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "27225MG"),
-               },
-       },
-       {
-               /* Reported by Paul Ionescu <i_p_a_u_l@yahoo.com> */
-               .ident = "IBM ThinkPad T41 (2373-TG5)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2373TG5"),
-               },
-       },
-       {
-               /* Reported by Michele Lamarca <lammic@gmail.com> */
-               .ident = "IBM ThinkPad T40 (2373-22G)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "237322G"),
-               },
-       },
-       {
-               /* Reported by Henrik Brix Andersen <brix@gentoo.org> */
-               .ident = "IBM ThinkPad X31 (2672-XXH)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "2672XXH"),
-               },
-       },
-       {
-               /* Reported by Matthew Saltzman <mjs@clemson.edu> */
-               .ident = "IBM ThinkPad T41 (2373-7JU)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "23737JU"),
-               },
-       },
-       { },
-       /* Negative reports: */
-       /* IBM thinkpad T30 2366 -> machine hangs 
-          Reported by: Jakob Schiotz <schiotz@fysik.dtu.dk> */
-       /* IBM thinkpad T42p 2373-KUU -> machine hangs as X starts
-          Reported by: Dax Kelson <dax@gurulabs.com> */
-       /* IBM ThinkPad X31 2672-XXH -> works, but doesn't fix the LCD 
-          backlight on during S3 issue.
-          Reported by: Henrik Brix Andersen <brix@gentoo.org> */
+
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+struct radeon_device_id {
+        const char *ident;                     /* (arbitrary) Name */
+        const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
+        const unsigned short subsystem_device; /* Subsystem Device ID */
+       const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
+       const reinit_function_ptr new_reinit_func;   /* changed reinit_func */
 };
 
-extern int radeon_force_sleep;
-#endif
+#define BUGFIX(model, sv, sd, pm, fn) { \
+       .ident = model, \
+       .subsystem_vendor = sv, \
+       .subsystem_device = sd, \
+       .pm_mode_modifier = pm, \
+       .new_reinit_func  = fn  \
+}
+
+static struct radeon_device_id radeon_workaround_list[] = {
+       BUGFIX("IBM Thinkpad R32",
+              PCI_VENDOR_ID_IBM, 0x1905,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R40",
+              PCI_VENDOR_ID_IBM, 0x0526,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R40",
+              PCI_VENDOR_ID_IBM, 0x0527,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R50/R51/T40/T41",
+              PCI_VENDOR_ID_IBM, 0x0531,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad R51/T40/T41/T42",
+              PCI_VENDOR_ID_IBM, 0x0530,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T30",
+              PCI_VENDOR_ID_IBM, 0x0517,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T40p",
+              PCI_VENDOR_ID_IBM, 0x054d,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad T42",
+              PCI_VENDOR_ID_IBM, 0x0550,
+              radeon_pm_d2, NULL),
+       BUGFIX("IBM Thinkpad X31/X32",
+              PCI_VENDOR_ID_IBM, 0x052f,
+              radeon_pm_d2, NULL),
+       BUGFIX("Samsung P35",
+              PCI_VENDOR_ID_SAMSUNG, 0xc00c,
+              radeon_pm_off, radeon_reinitialize_M10),
+       BUGFIX("Acer Aspire 2010",
+              PCI_VENDOR_ID_AI, 0x0061,
+              radeon_pm_off, radeon_reinitialize_M10),
+       { .ident = NULL }
+};
+
+static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+       struct radeon_device_id *id;
+
+       for (id = radeon_workaround_list; id->ident != NULL; id++ )
+               if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
+                   (id->subsystem_device == rinfo->pdev->subsystem_device )) {
+
+                       /* we found a device that requires workaround */
+                       printk(KERN_DEBUG "radeonfb: %s detected"
+                              ", enabling workaround\n", id->ident);
+
+                       rinfo->pm_mode |= id->pm_mode_modifier;
+
+                       if (id->new_reinit_func != NULL)
+                               rinfo->reinit_func = id->new_reinit_func;
+
+                       return 1;
+               }
+       return 0;  /* not found */
+}
+
+#else  /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+        return 0;
+}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+
+
 
 static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
 {
@@ -312,9 +158,9 @@ static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
                 OUTPLL(pllSCLK_CNTL, tmp);
                return;
        }
-       /* RV350 (M10) */
+       /* RV350 (M10/M11) */
        if (rinfo->family == CHIP_FAMILY_RV350) {
-                /* for RV350/M10, no delays are required. */
+                /* for RV350/M10/M11, no delays are required. */
                 tmp = INPLL(pllSCLK_CNTL2);
                 tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
                         SCLK_CNTL2__R300_FORCE_GA  |
@@ -498,7 +344,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
                return;
        }
 
-       /* M10 */
+       /* M10/M11 */
        if (rinfo->family == CHIP_FAMILY_RV350) {
                tmp = INPLL(pllSCLK_CNTL2);
                tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
@@ -1108,18 +954,18 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
         * now (until we get more info on how to compute the correct
         * value for various X86 bridges).
         */
-
 #ifdef CONFIG_PPC_PMAC
-       /* AGP PLL control */
-       if (rinfo->family <= CHIP_FAMILY_RV280) {
-               OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
-
-               OUTREG(BUS_CNTL1,
-                      (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
-                      | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));   // 440BX
-       } else {
-               OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
-               OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+       if (machine_is(powermac)) {
+               /* AGP PLL control */
+               if (rinfo->family <= CHIP_FAMILY_RV280) {
+                       OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
+                       OUTREG(BUS_CNTL1,
+                              (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
+                              | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));   // 440BX
+               } else {
+                       OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
+                       OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+               }
        }
 #endif
 
@@ -1413,7 +1259,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
        OUTREG( CRTC_GEN_CNTL,  (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
        OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
   
-       /* This is the code for the Aluminium PowerBooks M10 */
+       /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
        if (rinfo->family == CHIP_FAMILY_RV350) {
                u32 sdram_mode_reg = rinfo->save_regs[35];
                static u32 default_mrtable[] =
@@ -1425,7 +1271,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
                          0x21320032, 0xa1320032, 0x21320032, 0xffffffff,
                          0x31320032 };
 
-               u32 *mrtable = default_mrtable;
+               const u32 *mrtable = default_mrtable;
                int i, mrtable_size = ARRAY_SIZE(default_mrtable);
 
                mdelay(30);
@@ -1444,7 +1290,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
                if (rinfo->of_node != NULL) {
                        int size;
 
-                       mrtable = (u32 *)get_property(rinfo->of_node, "ATY,MRT", &size);
+                       mrtable = get_property(rinfo->of_node, "ATY,MRT", &size);
                        if (mrtable)
                                mrtable_size = size >> 2;
                        else
@@ -1579,8 +1425,6 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
        mdelay( 15);
 }
 
-#ifdef CONFIG_PPC_OF
-
 static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
 {
        u32 tmp, tmp2;
@@ -2094,6 +1938,8 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
        radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
 }
 
+#ifdef CONFIG_PPC_OF
+
 static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
 {
        OUTREG(MC_CNTL, rinfo->save_regs[46]);
@@ -2338,7 +2184,7 @@ static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo)
        OUTREG(0x2ec, 0x6332a3f0);
        mdelay(17);
 
-       OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);;
+       OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);
        OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
 
        mdelay(40);
@@ -2778,25 +2624,28 @@ static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
 }
 
 
-int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
        int i;
 
-       if (state == pdev->dev.power.power_state)
+       if (mesg.event == pdev->dev.power.power_state.event)
                return 0;
 
-       printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n",
-              pci_name(pdev), state);
+       printk(KERN_DEBUG "radeonfb (%s): suspending for event: %d...\n",
+              pci_name(pdev), mesg.event);
 
        /* For suspend-to-disk, we cheat here. We don't suspend anything and
         * let fbcon continue drawing until we are all set. That shouldn't
         * really cause any problem at this point, provided that the wakeup
         * code knows that any state in memory may not match the HW
         */
-       if (state != PM_SUSPEND_MEM)
+       switch (mesg.event) {
+       case PM_EVENT_FREEZE:           /* about to take snapshot */
+       case PM_EVENT_PRETHAW:          /* before restoring snapshot */
                goto done;
+       }
 
        acquire_console_sem();
 
@@ -2863,7 +2712,7 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        release_console_sem();
 
  done:
-       pdev->dev.power.power_state = state;
+       pdev->dev.power.power_state = mesg;
 
        return 0;
 }
@@ -2874,7 +2723,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
         struct radeonfb_info *rinfo = info->par;
        int rc = 0;
 
-       if (pdev->dev.power.power_state == 0)
+       if (pdev->dev.power.power_state.event == PM_EVENT_ON)
                return 0;
 
        if (rinfo->no_schedule) {
@@ -2884,7 +2733,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
                acquire_console_sem();
 
        printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
-              pci_name(pdev), pdev->dev.power.power_state);
+              pci_name(pdev), pdev->dev.power.power_state.event);
 
 
        if (pci_enable_device(pdev)) {
@@ -2895,7 +2744,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
        }
        pci_set_master(pdev);
 
-       if (pdev->dev.power.power_state == PM_SUSPEND_MEM) {
+       if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
                /* Wakeup chip. Check from config space if we were powered off
                 * (todo: additionally, check CLK_PIN_CNTL too)
                 */
@@ -2971,7 +2820,7 @@ static void radeonfb_early_resume(void *data)
 
 #endif /* CONFIG_PM */
 
-void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
 {
        /* Find PM registers in config space if any*/
        rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
@@ -2986,22 +2835,25 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
                printk("radeonfb: Dynamic Clock Power Management disabled\n");
        }
 
+#if defined(CONFIG_PM)
+#if defined(CONFIG_PPC_PMAC)
        /* Check if we can power manage on suspend/resume. We can do
         * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
         * "Mac" cards, but that's all. We need more infos about what the
         * BIOS does tho. Right now, all this PM stuff is pmac-only for that
         * reason. --BenH
         */
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
-       if (_machine == _MACH_Pmac && rinfo->of_node) {
+       if (machine_is(powermac) && rinfo->of_node) {
                if (rinfo->is_mobility && rinfo->pm_reg &&
                    rinfo->family <= CHIP_FAMILY_RV250)
                        rinfo->pm_mode |= radeon_pm_d2;
 
                /* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
-                * in some desktop G4s), and Via (M9+ chip on iBook G4)
+                * in some desktop G4s), Via (M9+ chip on iBook G4) and
+                * Snowy (M11 chip on iBook G4 manufactured after July 2005)
                 */
-               if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) {
+               if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") ||
+                   !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) {
                        rinfo->reinit_func = radeon_reinitialize_M10;
                        rinfo->pm_mode |= radeon_pm_off;
                }
@@ -3034,35 +2886,25 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
                OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
 #endif
        }
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */
+#endif /* defined(CONFIG_PPC_PMAC) */
+#endif /* defined(CONFIG_PM) */
 
-/* The PM code also works on some PC laptops.
- * Only a few models are actually tested so Your mileage may vary.
- * We can do D2 on at least M7 and M9 on some IBM ThinkPad T41 models.
- */
-#if defined(CONFIG_PM) && defined(CONFIG_X86)
-       if (radeon_force_sleep || dmi_check_system(radeonfb_dmi_table)) {
-               if (radeon_force_sleep)
-                       printk("radeonfb: forcefully enabling sleep mode\n");
-               else
-                       printk("radeonfb: enabling sleep mode\n");
-
-               if (rinfo->is_mobility && rinfo->pm_reg &&
-                   rinfo->family <= CHIP_FAMILY_RV250)
-                       rinfo->pm_mode |= radeon_pm_d2;
+       if (ignore_devlist)
+               printk(KERN_DEBUG
+                      "radeonfb: skipping test for device workarounds\n");
+       else
+               radeon_apply_workarounds(rinfo);
 
-               /* Power down TV DAC, that saves a significant amount of power,
-                * we'll have something better once we actually have some TVOut
-                * support
-                */
-               OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
+       if (force_sleep) {
+               printk(KERN_DEBUG
+                      "radeonfb: forcefully enabling D2 sleep mode\n");
+               rinfo->pm_mode |= radeon_pm_d2;
        }
-#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
 }
 
 void radeonfb_pm_exit(struct radeonfb_info *rinfo)
 {
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
        if (rinfo->pm_mode != radeon_pm_none)
                pmac_set_early_video_resume(NULL, NULL);
 #endif