Lines 27-32
Link Here
|
27 |
|
27 |
|
28 |
#include "ati_ids.h" |
28 |
#include "ati_ids.h" |
29 |
|
29 |
|
|
|
30 |
#if defined(CONFIG_PM) && defined(CONFIG_X86) |
31 |
/* DMI is used to detect PC laptops known to support D2 sleep */ |
32 |
#include <linux/dmi.h> |
33 |
|
34 |
/* Whitelist of PC laptops known to support D2 sleep */ |
35 |
static int radeon_sleep_dmi_whitelisted(struct dmi_system_id *id) { |
36 |
printk(KERN_DEBUG "radeonfb: %s detected, enabling D2 sleep\n", id->ident); |
37 |
return 1; |
38 |
} |
39 |
#define RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL(model) { \ |
40 |
.ident = "IBM ThinkPad " model, \ |
41 |
.callback = radeon_sleep_dmi_whitelisted, \ |
42 |
.matches = { \ |
43 |
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ |
44 |
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad " model) \ |
45 |
} \ |
46 |
} |
47 |
#define RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE(type,name) { \ |
48 |
.ident = "IBM ThinkPad " name " (" type ")", \ |
49 |
.callback = radeon_sleep_dmi_whitelisted, \ |
50 |
.matches = { \ |
51 |
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ |
52 |
DMI_MATCH(DMI_PRODUCT_NAME, type) \ |
53 |
} \ |
54 |
} |
55 |
static struct dmi_system_id radeon_sleep_dmi_whitelist[] = { |
56 |
// This models all had at least one positive report and no negative one |
57 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("R50"), |
58 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("R51"), |
59 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T40p"), |
60 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T40"), |
61 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T41p"), |
62 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T41"), |
63 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T42"), |
64 |
// Same for this ones, but it's still to confirm that the DMI string exists |
65 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("T30"), |
66 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("R32"), |
67 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_MODEL("X31"), |
68 |
// R40 does not have the version DMI string |
69 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2681","R40"), |
70 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2682","R40"), |
71 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2683","R40"), |
72 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2722","R40"), |
73 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2723","R40"), |
74 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2724","R40"), |
75 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2892","R40"), |
76 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2893","R40"), |
77 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2896","R40"), |
78 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2897","R40"), |
79 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2898","R40"), |
80 |
RADEON_SLEEP_THINKPAD_DMI_MATCH_TYPE("2899","R40"), |
81 |
{ .ident = NULL } |
82 |
}; |
83 |
|
84 |
/* Need a blacklist too because DMI matching is done by substrings search */ |
85 |
#define RADEON_SLEEP_THINKPAD_DMI_UNMATCH_MODEL(model) { \ |
86 |
.ident = "IBM ThinkPad " model, \ |
87 |
.matches = { \ |
88 |
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ |
89 |
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad " model) \ |
90 |
} \ |
91 |
} |
92 |
#define RADEON_SLEEP_THINKPAD_DMI_UNMATCH_TYPE(type,name) { \ |
93 |
.ident = "IBM ThinkPad " name " (" type ")", \ |
94 |
.matches = { \ |
95 |
DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \ |
96 |
DMI_MATCH(DMI_PRODUCT_NAME, type) \ |
97 |
} \ |
98 |
} |
99 |
static struct dmi_system_id radeon_sleep_dmi_blacklist[] = { |
100 |
// Excluded by lack of positive report, and possibly wrong substring match |
101 |
RADEON_SLEEP_THINKPAD_DMI_UNMATCH_MODEL("R50p"), |
102 |
RADEON_SLEEP_THINKPAD_DMI_UNMATCH_MODEL("R50e"), |
103 |
RADEON_SLEEP_THINKPAD_DMI_UNMATCH_MODEL("R51e"), |
104 |
// T42p excluded because of one negative report and no positive one |
105 |
RADEON_SLEEP_THINKPAD_DMI_UNMATCH_MODEL("T42p"), |
106 |
{ .ident = NULL } |
107 |
}; |
108 |
|
109 |
/* Macro for checking DMI infos against the whitelist */ |
110 |
#define radeon_sleep_match_whitelist() \ |
111 |
(! dmi_check_system(radeon_sleep_dmi_blacklist) \ |
112 |
&& dmi_check_system(radeon_sleep_dmi_whitelist)) |
113 |
|
114 |
/* Module parameters to ignore the whitelist */ |
115 |
extern int force_sleep; |
116 |
extern int nosleep; |
117 |
#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */ |
118 |
|
30 |
static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) |
119 |
static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) |
31 |
{ |
120 |
{ |
32 |
u32 tmp; |
121 |
u32 tmp; |
Lines 852-870
static void radeon_pm_setup_for_suspend(
Link Here
|
852 |
/* because both INPLL and OUTPLL take the same lock, that's why. */ |
941 |
/* because both INPLL and OUTPLL take the same lock, that's why. */ |
853 |
tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; |
942 |
tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; |
854 |
OUTPLL( pllMCLK_MISC, tmp); |
943 |
OUTPLL( pllMCLK_MISC, tmp); |
855 |
|
944 |
|
|
|
945 |
/* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset |
946 |
* and radeon chip dependent. Thus we only enable it on Mac for |
947 |
* now (until we get more info on how to compute the correct |
948 |
* value for various X86 bridges). |
949 |
*/ |
950 |
#ifdef CONFIG_PPC_PMAC |
951 |
if (machine_is(powermac)) { |
856 |
/* AGP PLL control */ |
952 |
/* AGP PLL control */ |
857 |
if (rinfo->family <= CHIP_FAMILY_RV280) { |
953 |
if (rinfo->family <= CHIP_FAMILY_RV280) { |
858 |
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); |
954 |
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); |
859 |
|
955 |
|
860 |
OUTREG(BUS_CNTL1, |
956 |
OUTREG(BUS_CNTL1, |
861 |
(INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) |
957 |
(INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) |
862 |
| (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX |
958 |
| (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX |
863 |
} else { |
959 |
} else { |
864 |
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); |
960 |
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); |
865 |
OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); |
961 |
OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); |
866 |
} |
962 |
} |
867 |
|
963 |
} |
|
|
964 |
#endif |
868 |
OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) |
965 |
OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) |
869 |
& ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); |
966 |
& ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); |
870 |
|
967 |
|
Lines 2789-2794
void radeonfb_pm_init(struct radeonfb_in
Link Here
|
2789 |
#endif |
2886 |
#endif |
2790 |
} |
2887 |
} |
2791 |
#endif /* defined(CONFIG_PPC_PMAC) */ |
2888 |
#endif /* defined(CONFIG_PPC_PMAC) */ |
|
|
2889 |
|
2890 |
/* The PM code also works on some PC laptops. |
2891 |
* We can do D2 on at least M7 and M9 on some IBM ThinkPad models. |
2892 |
*/ |
2893 |
#if defined(CONFIG_X86) |
2894 |
if (!nosleep && (force_sleep || radeon_sleep_match_whitelist())) { |
2895 |
if (force_sleep) |
2896 |
printk(KERN_DEBUG "radeonfb: forcefully enabling D2 sleep mode\n"); |
2897 |
|
2898 |
if (rinfo->is_mobility && rinfo->pm_reg && |
2899 |
rinfo->family <= CHIP_FAMILY_RV250) |
2900 |
rinfo->pm_mode |= radeon_pm_d2; |
2901 |
} |
2902 |
#endif /* defined(CONFIG_X86) */ |
2792 |
#endif /* defined(CONFIG_PM) */ |
2903 |
#endif /* defined(CONFIG_PM) */ |
2793 |
} |
2904 |
} |
2794 |
|
2905 |
|