#include <linux/agp_backend.h>
#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
+#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
#endif
#include "ati_ids.h"
-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!
- */
-
-#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 */
-};
-
-#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),
- { .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)
{
u32 tmp;
/* because both INPLL and OUTPLL take the same lock, that's why. */
tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
OUTPLL( pllMCLK_MISC, tmp);
+
+ /* AGP PLL control */
+ if (rinfo->family <= CHIP_FAMILY_RV280) {
+ OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
- /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
- * and radeon chip dependent. Thus we only enable it on Mac for
- * now (until we get more info on how to compute the correct
- * value for various X86 bridges).
- */
-#ifdef CONFIG_PPC_PMAC
- 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);
- }
+ 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
OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
& ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
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);
#endif /* CONFIG_PM */
-void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
{
/* Find PM registers in config space if any*/
rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
}
#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 (machine_is(powermac) && rinfo->of_node) {
+ /* Special case for Samsung P35 laptops
+ */
+ if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
+ (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
+ (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
+ (rinfo->pdev->subsystem_device == 0xc00c)) {
+ rinfo->reinit_func = radeon_reinitialize_M10;
+ rinfo->pm_mode |= radeon_pm_off;
+ }
+#if defined(CONFIG_PPC_PMAC)
+ if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
rinfo->pm_mode |= radeon_pm_d2;
}
#endif /* defined(CONFIG_PPC_PMAC) */
#endif /* defined(CONFIG_PM) */
-
- if (ignore_devlist)
- printk(KERN_DEBUG
- "radeonfb: skipping test for device workarounds\n");
- else
- radeon_apply_workarounds(rinfo);
-
- if (force_sleep) {
- printk(KERN_DEBUG
- "radeonfb: forcefully enabling D2 sleep mode\n");
- rinfo->pm_mode |= radeon_pm_d2;
- }
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)