aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/aty
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
commit57cad8084e0837e0f2c97da789ec9b3f36809be9 (patch)
treee9c790afb4286f78cb08d9664f58baa7e876fe55 /drivers/video/aty
parentcb18bd40030c879cd93fef02fd579f74dbab473d (diff)
parent49b1e3ea19b1c95c2f012b8331ffb3b169e4c042 (diff)
Merge branch 'merge'
Diffstat (limited to 'drivers/video/aty')
-rw-r--r--drivers/video/aty/aty128fb.c70
-rw-r--r--drivers/video/aty/atyfb_base.c57
-rw-r--r--drivers/video/aty/radeon_base.c19
-rw-r--r--drivers/video/aty/radeon_pm.c146
-rw-r--r--drivers/video/aty/radeonfb.h6
5 files changed, 215 insertions, 83 deletions
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 72c589109471..8b08121b390b 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -52,7 +52,6 @@
52#include <linux/errno.h> 52#include <linux/errno.h>
53#include <linux/string.h> 53#include <linux/string.h>
54#include <linux/mm.h> 54#include <linux/mm.h>
55#include <linux/tty.h>
56#include <linux/slab.h> 55#include <linux/slab.h>
57#include <linux/vmalloc.h> 56#include <linux/vmalloc.h>
58#include <linux/delay.h> 57#include <linux/delay.h>
@@ -457,6 +456,10 @@ static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
457static void wait_for_idle(struct aty128fb_par *par); 456static void wait_for_idle(struct aty128fb_par *par);
458static u32 depth_to_dst(u32 depth); 457static u32 depth_to_dst(u32 depth);
459 458
459#ifdef CONFIG_FB_ATY128_BACKLIGHT
460static void aty128_bl_set_power(struct fb_info *info, int power);
461#endif
462
460#define BIOS_IN8(v) (readb(bios + (v))) 463#define BIOS_IN8(v) (readb(bios + (v)))
461#define BIOS_IN16(v) (readb(bios + (v)) | \ 464#define BIOS_IN16(v) (readb(bios + (v)) | \
462 (readb(bios + (v) + 1) << 8)) 465 (readb(bios + (v) + 1) << 8))
@@ -1258,25 +1261,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
1258 reg &= ~LVDS_DISPLAY_DIS; 1261 reg &= ~LVDS_DISPLAY_DIS;
1259 aty_st_le32(LVDS_GEN_CNTL, reg); 1262 aty_st_le32(LVDS_GEN_CNTL, reg);
1260#ifdef CONFIG_FB_ATY128_BACKLIGHT 1263#ifdef CONFIG_FB_ATY128_BACKLIGHT
1261 mutex_lock(&info->bl_mutex); 1264 aty128_bl_set_power(info, FB_BLANK_UNBLANK);
1262 if (info->bl_dev) {
1263 down(&info->bl_dev->sem);
1264 info->bl_dev->props->update_status(info->bl_dev);
1265 up(&info->bl_dev->sem);
1266 }
1267 mutex_unlock(&info->bl_mutex);
1268#endif 1265#endif
1269 } else { 1266 } else {
1270#ifdef CONFIG_FB_ATY128_BACKLIGHT 1267#ifdef CONFIG_FB_ATY128_BACKLIGHT
1271 mutex_lock(&info->bl_mutex); 1268 aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
1272 if (info->bl_dev) {
1273 down(&info->bl_dev->sem);
1274 info->bl_dev->props->brightness = 0;
1275 info->bl_dev->props->power = FB_BLANK_POWERDOWN;
1276 info->bl_dev->props->update_status(info->bl_dev);
1277 up(&info->bl_dev->sem);
1278 }
1279 mutex_unlock(&info->bl_mutex);
1280#endif 1269#endif
1281 reg = aty_ld_le32(LVDS_GEN_CNTL); 1270 reg = aty_ld_le32(LVDS_GEN_CNTL);
1282 reg |= LVDS_DISPLAY_DIS; 1271 reg |= LVDS_DISPLAY_DIS;
@@ -1703,6 +1692,7 @@ static int __devinit aty128fb_setup(char *options)
1703 1692
1704static struct backlight_properties aty128_bl_data; 1693static struct backlight_properties aty128_bl_data;
1705 1694
1695/* Call with fb_info->bl_mutex held */
1706static int aty128_bl_get_level_brightness(struct aty128fb_par *par, 1696static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
1707 int level) 1697 int level)
1708{ 1698{
@@ -1710,10 +1700,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
1710 int atylevel; 1700 int atylevel;
1711 1701
1712 /* Get and convert the value */ 1702 /* Get and convert the value */
1713 mutex_lock(&info->bl_mutex);
1714 atylevel = MAX_LEVEL - 1703 atylevel = MAX_LEVEL -
1715 (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); 1704 (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
1716 mutex_unlock(&info->bl_mutex);
1717 1705
1718 if (atylevel < 0) 1706 if (atylevel < 0)
1719 atylevel = 0; 1707 atylevel = 0;
@@ -1731,7 +1719,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
1731/* That one prevents proper CRT output with LCD off */ 1719/* That one prevents proper CRT output with LCD off */
1732#undef BACKLIGHT_DAC_OFF 1720#undef BACKLIGHT_DAC_OFF
1733 1721
1734static int aty128_bl_update_status(struct backlight_device *bd) 1722/* Call with fb_info->bl_mutex held */
1723static int __aty128_bl_update_status(struct backlight_device *bd)
1735{ 1724{
1736 struct aty128fb_par *par = class_get_devdata(&bd->class_dev); 1725 struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
1737 unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); 1726 unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
@@ -1784,6 +1773,19 @@ static int aty128_bl_update_status(struct backlight_device *bd)
1784 return 0; 1773 return 0;
1785} 1774}
1786 1775
1776static int aty128_bl_update_status(struct backlight_device *bd)
1777{
1778 struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
1779 struct fb_info *info = pci_get_drvdata(par->pdev);
1780 int ret;
1781
1782 mutex_lock(&info->bl_mutex);
1783 ret = __aty128_bl_update_status(bd);
1784 mutex_unlock(&info->bl_mutex);
1785
1786 return ret;
1787}
1788
1787static int aty128_bl_get_brightness(struct backlight_device *bd) 1789static int aty128_bl_get_brightness(struct backlight_device *bd)
1788{ 1790{
1789 return bd->props->brightness; 1791 return bd->props->brightness;
@@ -1796,6 +1798,16 @@ static struct backlight_properties aty128_bl_data = {
1796 .max_brightness = (FB_BACKLIGHT_LEVELS - 1), 1798 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
1797}; 1799};
1798 1800
1801static void aty128_bl_set_power(struct fb_info *info, int power)
1802{
1803 mutex_lock(&info->bl_mutex);
1804 up(&info->bl_dev->sem);
1805 info->bl_dev->props->power = power;
1806 __aty128_bl_update_status(info->bl_dev);
1807 down(&info->bl_dev->sem);
1808 mutex_unlock(&info->bl_mutex);
1809}
1810
1799static void aty128_bl_init(struct aty128fb_par *par) 1811static void aty128_bl_init(struct aty128fb_par *par)
1800{ 1812{
1801 struct fb_info *info = pci_get_drvdata(par->pdev); 1813 struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2198,12 +2210,8 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
2198 return 0; 2210 return 0;
2199 2211
2200#ifdef CONFIG_FB_ATY128_BACKLIGHT 2212#ifdef CONFIG_FB_ATY128_BACKLIGHT
2201 if (machine_is(powermac) && blank) { 2213 if (machine_is(powermac) && blank)
2202 down(&fb->bl_dev->sem); 2214 aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
2203 fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
2204 fb->bl_dev->props->update_status(fb->bl_dev);
2205 up(&fb->bl_dev->sem);
2206 }
2207#endif 2215#endif
2208 2216
2209 if (blank & FB_BLANK_VSYNC_SUSPEND) 2217 if (blank & FB_BLANK_VSYNC_SUSPEND)
@@ -2219,14 +2227,12 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
2219 aty128_set_crt_enable(par, par->crt_on && !blank); 2227 aty128_set_crt_enable(par, par->crt_on && !blank);
2220 aty128_set_lcd_enable(par, par->lcd_on && !blank); 2228 aty128_set_lcd_enable(par, par->lcd_on && !blank);
2221 } 2229 }
2230
2222#ifdef CONFIG_FB_ATY128_BACKLIGHT 2231#ifdef CONFIG_FB_ATY128_BACKLIGHT
2223 if (machine_is(powermac) && !blank) { 2232 if (machine_is(powermac) && !blank)
2224 down(&fb->bl_dev->sem); 2233 aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
2225 fb->bl_dev->props->power = FB_BLANK_UNBLANK;
2226 fb->bl_dev->props->update_status(fb->bl_dev);
2227 up(&fb->bl_dev->sem);
2228 }
2229#endif 2234#endif
2235
2230 return 0; 2236 return 0;
2231} 2237}
2232 2238
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 0c9706746d79..053ff63365b7 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2129,15 +2129,14 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2129 2129
2130static struct backlight_properties aty_bl_data; 2130static struct backlight_properties aty_bl_data;
2131 2131
2132/* Call with fb_info->bl_mutex held */
2132static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) 2133static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2133{ 2134{
2134 struct fb_info *info = pci_get_drvdata(par->pdev); 2135 struct fb_info *info = pci_get_drvdata(par->pdev);
2135 int atylevel; 2136 int atylevel;
2136 2137
2137 /* Get and convert the value */ 2138 /* Get and convert the value */
2138 mutex_lock(&info->bl_mutex);
2139 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; 2139 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2140 mutex_unlock(&info->bl_mutex);
2141 2140
2142 if (atylevel < 0) 2141 if (atylevel < 0)
2143 atylevel = 0; 2142 atylevel = 0;
@@ -2147,7 +2146,8 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2147 return atylevel; 2146 return atylevel;
2148} 2147}
2149 2148
2150static int aty_bl_update_status(struct backlight_device *bd) 2149/* Call with fb_info->bl_mutex held */
2150static int __aty_bl_update_status(struct backlight_device *bd)
2151{ 2151{
2152 struct atyfb_par *par = class_get_devdata(&bd->class_dev); 2152 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2153 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); 2153 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
@@ -2172,6 +2172,19 @@ static int aty_bl_update_status(struct backlight_device *bd)
2172 return 0; 2172 return 0;
2173} 2173}
2174 2174
2175static int aty_bl_update_status(struct backlight_device *bd)
2176{
2177 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2178 struct fb_info *info = pci_get_drvdata(par->pdev);
2179 int ret;
2180
2181 mutex_lock(&info->bl_mutex);
2182 ret = __aty_bl_update_status(bd);
2183 mutex_unlock(&info->bl_mutex);
2184
2185 return ret;
2186}
2187
2175static int aty_bl_get_brightness(struct backlight_device *bd) 2188static int aty_bl_get_brightness(struct backlight_device *bd)
2176{ 2189{
2177 return bd->props->brightness; 2190 return bd->props->brightness;
@@ -2184,6 +2197,16 @@ static struct backlight_properties aty_bl_data = {
2184 .max_brightness = (FB_BACKLIGHT_LEVELS - 1), 2197 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
2185}; 2198};
2186 2199
2200static void aty_bl_set_power(struct fb_info *info, int power)
2201{
2202 mutex_lock(&info->bl_mutex);
2203 up(&info->bl_dev->sem);
2204 info->bl_dev->props->power = power;
2205 __aty_bl_update_status(info->bl_dev);
2206 down(&info->bl_dev->sem);
2207 mutex_unlock(&info->bl_mutex);
2208}
2209
2187static void aty_bl_init(struct atyfb_par *par) 2210static void aty_bl_init(struct atyfb_par *par)
2188{ 2211{
2189 struct fb_info *info = pci_get_drvdata(par->pdev); 2212 struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2789,17 +2812,9 @@ static int atyfb_blank(int blank, struct fb_info *info)
2789 if (par->lock_blank || par->asleep) 2812 if (par->lock_blank || par->asleep)
2790 return 0; 2813 return 0;
2791 2814
2792#ifdef CONFIG_PMAC_BACKLIGHT 2815#ifdef CONFIG_FB_ATY_BACKLIGHT
2793 if (machine_is(powermac) && blank > FB_BLANK_NORMAL) { 2816 if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
2794 mutex_lock(&info->bl_mutex); 2817 aty_bl_set_power(info, FB_BLANK_POWERDOWN);
2795 if (info->bl_dev) {
2796 down(&info->bl_dev->sem);
2797 info->bl_dev->props->power = FB_BLANK_POWERDOWN;
2798 info->bl_dev->props->update_status(info->bl_dev);
2799 up(&info->bl_dev->sem);
2800 }
2801 mutex_unlock(&info->bl_mutex);
2802 }
2803#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2818#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2804 if (par->lcd_table && blank > FB_BLANK_NORMAL && 2819 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2805 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2820 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2829,17 +2844,9 @@ static int atyfb_blank(int blank, struct fb_info *info)
2829 } 2844 }
2830 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2845 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2831 2846
2832#ifdef CONFIG_PMAC_BACKLIGHT 2847#ifdef CONFIG_FB_ATY_BACKLIGHT
2833 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) { 2848 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
2834 mutex_lock(&info->bl_mutex); 2849 aty_bl_set_power(info, FB_BLANK_UNBLANK);
2835 if (info->bl_dev) {
2836 down(&info->bl_dev->sem);
2837 info->bl_dev->props->power = FB_BLANK_UNBLANK;
2838 info->bl_dev->props->update_status(info->bl_dev);
2839 up(&info->bl_dev->sem);
2840 }
2841 mutex_unlock(&info->bl_mutex);
2842 }
2843#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2850#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2844 if (par->lcd_table && blank <= FB_BLANK_NORMAL && 2851 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2845 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2852 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 60c37add2579..0ed577e7cc21 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -58,7 +58,6 @@
58#include <linux/errno.h> 58#include <linux/errno.h>
59#include <linux/string.h> 59#include <linux/string.h>
60#include <linux/mm.h> 60#include <linux/mm.h>
61#include <linux/tty.h>
62#include <linux/slab.h> 61#include <linux/slab.h>
63#include <linux/delay.h> 62#include <linux/delay.h>
64#include <linux/time.h> 63#include <linux/time.h>
@@ -267,6 +266,8 @@ static int force_measure_pll = 0;
267#ifdef CONFIG_MTRR 266#ifdef CONFIG_MTRR
268static int nomtrr = 0; 267static int nomtrr = 0;
269#endif 268#endif
269static int force_sleep;
270static int ignore_devlist;
270 271
271/* 272/*
272 * prototypes 273 * prototypes
@@ -2328,9 +2329,9 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
2328 /* -2 is special: means ON on mobility chips and do not 2329 /* -2 is special: means ON on mobility chips and do not
2329 * change on others 2330 * change on others
2330 */ 2331 */
2331 radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); 2332 radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
2332 } else 2333 } else
2333 radeonfb_pm_init(rinfo, default_dynclk); 2334 radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
2334 2335
2335 pci_set_drvdata(pdev, info); 2336 pci_set_drvdata(pdev, info);
2336 2337
@@ -2478,6 +2479,12 @@ static int __init radeonfb_setup (char *options)
2478 force_measure_pll = 1; 2479 force_measure_pll = 1;
2479 } else if (!strncmp(this_opt, "ignore_edid", 11)) { 2480 } else if (!strncmp(this_opt, "ignore_edid", 11)) {
2480 ignore_edid = 1; 2481 ignore_edid = 1;
2482#if defined(CONFIG_PM) && defined(CONFIG_X86)
2483 } else if (!strncmp(this_opt, "force_sleep", 11)) {
2484 force_sleep = 1;
2485 } else if (!strncmp(this_opt, "ignore_devlist", 14)) {
2486 ignore_devlist = 1;
2487#endif
2481 } else 2488 } else
2482 mode_option = this_opt; 2489 mode_option = this_opt;
2483 } 2490 }
@@ -2533,3 +2540,9 @@ module_param(panel_yres, int, 0);
2533MODULE_PARM_DESC(panel_yres, "int: set panel yres"); 2540MODULE_PARM_DESC(panel_yres, "int: set panel yres");
2534module_param(mode_option, charp, 0); 2541module_param(mode_option, charp, 0);
2535MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); 2542MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
2543#if defined(CONFIG_PM) && defined(CONFIG_X86)
2544module_param(force_sleep, bool, 0);
2545MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
2546module_param(ignore_devlist, bool, 0);
2547MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
2548#endif
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index b9b9396d3bde..e308ed2d249a 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -27,6 +27,99 @@
27 27
28#include "ati_ids.h" 28#include "ati_ids.h"
29 29
30static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
31
32/*
33 * Workarounds for bugs in PC laptops:
34 * - enable D2 sleep in some IBM Thinkpads
35 * - special case for Samsung P35
36 *
37 * Whitelist by subsystem vendor/device because
38 * its the subsystem vendor's fault!
39 */
40
41#if defined(CONFIG_PM) && defined(CONFIG_X86)
42struct radeon_device_id {
43 const char *ident; /* (arbitrary) Name */
44 const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
45 const unsigned short subsystem_device; /* Subsystem Device ID */
46 const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
47 const reinit_function_ptr new_reinit_func; /* changed reinit_func */
48};
49
50#define BUGFIX(model, sv, sd, pm, fn) { \
51 .ident = model, \
52 .subsystem_vendor = sv, \
53 .subsystem_device = sd, \
54 .pm_mode_modifier = pm, \
55 .new_reinit_func = fn \
56}
57
58static struct radeon_device_id radeon_workaround_list[] = {
59 BUGFIX("IBM Thinkpad R32",
60 PCI_VENDOR_ID_IBM, 0x1905,
61 radeon_pm_d2, NULL),
62 BUGFIX("IBM Thinkpad R40",
63 PCI_VENDOR_ID_IBM, 0x0526,
64 radeon_pm_d2, NULL),
65 BUGFIX("IBM Thinkpad R40",
66 PCI_VENDOR_ID_IBM, 0x0527,
67 radeon_pm_d2, NULL),
68 BUGFIX("IBM Thinkpad R50/R51/T40/T41",
69 PCI_VENDOR_ID_IBM, 0x0531,
70 radeon_pm_d2, NULL),
71 BUGFIX("IBM Thinkpad R51/T40/T41/T42",
72 PCI_VENDOR_ID_IBM, 0x0530,
73 radeon_pm_d2, NULL),
74 BUGFIX("IBM Thinkpad T30",
75 PCI_VENDOR_ID_IBM, 0x0517,
76 radeon_pm_d2, NULL),
77 BUGFIX("IBM Thinkpad T40p",
78 PCI_VENDOR_ID_IBM, 0x054d,
79 radeon_pm_d2, NULL),
80 BUGFIX("IBM Thinkpad T42",
81 PCI_VENDOR_ID_IBM, 0x0550,
82 radeon_pm_d2, NULL),
83 BUGFIX("IBM Thinkpad X31/X32",
84 PCI_VENDOR_ID_IBM, 0x052f,
85 radeon_pm_d2, NULL),
86 BUGFIX("Samsung P35",
87 PCI_VENDOR_ID_SAMSUNG, 0xc00c,
88 radeon_pm_off, radeon_reinitialize_M10),
89 { .ident = NULL }
90};
91
92static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
93{
94 struct radeon_device_id *id;
95
96 for (id = radeon_workaround_list; id->ident != NULL; id++ )
97 if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
98 (id->subsystem_device == rinfo->pdev->subsystem_device )) {
99
100 /* we found a device that requires workaround */
101 printk(KERN_DEBUG "radeonfb: %s detected"
102 ", enabling workaround\n", id->ident);
103
104 rinfo->pm_mode |= id->pm_mode_modifier;
105
106 if (id->new_reinit_func != NULL)
107 rinfo->reinit_func = id->new_reinit_func;
108
109 return 1;
110 }
111 return 0; /* not found */
112}
113
114#else /* defined(CONFIG_PM) && defined(CONFIG_X86) */
115static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
116{
117 return 0;
118}
119#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
120
121
122
30static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) 123static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
31{ 124{
32 u32 tmp; 125 u32 tmp;
@@ -852,18 +945,26 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
852 /* because both INPLL and OUTPLL take the same lock, that's why. */ 945 /* because both INPLL and OUTPLL take the same lock, that's why. */
853 tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; 946 tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
854 OUTPLL( pllMCLK_MISC, tmp); 947 OUTPLL( pllMCLK_MISC, tmp);
855
856 /* AGP PLL control */
857 if (rinfo->family <= CHIP_FAMILY_RV280) {
858 OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
859 948
860 OUTREG(BUS_CNTL1, 949 /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
861 (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) 950 * and radeon chip dependent. Thus we only enable it on Mac for
862 | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX 951 * now (until we get more info on how to compute the correct
863 } else { 952 * value for various X86 bridges).
864 OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); 953 */
865 OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); 954#ifdef CONFIG_PPC_PMAC
955 if (machine_is(powermac)) {
956 /* AGP PLL control */
957 if (rinfo->family <= CHIP_FAMILY_RV280) {
958 OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
959 OUTREG(BUS_CNTL1,
960 (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
961 | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX
962 } else {
963 OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
964 OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
965 }
866 } 966 }
967#endif
867 968
868 OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) 969 OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
869 & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); 970 & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
@@ -2713,7 +2814,7 @@ static void radeonfb_early_resume(void *data)
2713 2814
2714#endif /* CONFIG_PM */ 2815#endif /* CONFIG_PM */
2715 2816
2716void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) 2817void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
2717{ 2818{
2718 /* Find PM registers in config space if any*/ 2819 /* Find PM registers in config space if any*/
2719 rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); 2820 rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
@@ -2729,22 +2830,13 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
2729 } 2830 }
2730 2831
2731#if defined(CONFIG_PM) 2832#if defined(CONFIG_PM)
2833#if defined(CONFIG_PPC_PMAC)
2732 /* Check if we can power manage on suspend/resume. We can do 2834 /* Check if we can power manage on suspend/resume. We can do
2733 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other 2835 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
2734 * "Mac" cards, but that's all. We need more infos about what the 2836 * "Mac" cards, but that's all. We need more infos about what the
2735 * BIOS does tho. Right now, all this PM stuff is pmac-only for that 2837 * BIOS does tho. Right now, all this PM stuff is pmac-only for that
2736 * reason. --BenH 2838 * reason. --BenH
2737 */ 2839 */
2738 /* Special case for Samsung P35 laptops
2739 */
2740 if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
2741 (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
2742 (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
2743 (rinfo->pdev->subsystem_device == 0xc00c)) {
2744 rinfo->reinit_func = radeon_reinitialize_M10;
2745 rinfo->pm_mode |= radeon_pm_off;
2746 }
2747#if defined(CONFIG_PPC_PMAC)
2748 if (machine_is(powermac) && rinfo->of_node) { 2840 if (machine_is(powermac) && rinfo->of_node) {
2749 if (rinfo->is_mobility && rinfo->pm_reg && 2841 if (rinfo->is_mobility && rinfo->pm_reg &&
2750 rinfo->family <= CHIP_FAMILY_RV250) 2842 rinfo->family <= CHIP_FAMILY_RV250)
@@ -2790,6 +2882,18 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
2790 } 2882 }
2791#endif /* defined(CONFIG_PPC_PMAC) */ 2883#endif /* defined(CONFIG_PPC_PMAC) */
2792#endif /* defined(CONFIG_PM) */ 2884#endif /* defined(CONFIG_PM) */
2885
2886 if (ignore_devlist)
2887 printk(KERN_DEBUG
2888 "radeonfb: skipping test for device workarounds\n");
2889 else
2890 radeon_apply_workarounds(rinfo);
2891
2892 if (force_sleep) {
2893 printk(KERN_DEBUG
2894 "radeonfb: forcefully enabling D2 sleep mode\n");
2895 rinfo->pm_mode |= radeon_pm_d2;
2896 }
2793} 2897}
2794 2898
2795void radeonfb_pm_exit(struct radeonfb_info *rinfo) 2899void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 38657b2d10eb..d5ff224a6258 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -273,6 +273,8 @@ enum radeon_pm_mode {
273 radeon_pm_off = 0x00000002, /* Can resume from D3 cold */ 273 radeon_pm_off = 0x00000002, /* Can resume from D3 cold */
274}; 274};
275 275
276typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo);
277
276struct radeonfb_info { 278struct radeonfb_info {
277 struct fb_info *info; 279 struct fb_info *info;
278 280
@@ -338,7 +340,7 @@ struct radeonfb_info {
338 int dynclk; 340 int dynclk;
339 int no_schedule; 341 int no_schedule;
340 enum radeon_pm_mode pm_mode; 342 enum radeon_pm_mode pm_mode;
341 void (*reinit_func)(struct radeonfb_info *rinfo); 343 reinit_function_ptr reinit_func;
342 344
343 /* Lock on register access */ 345 /* Lock on register access */
344 spinlock_t reg_lock; 346 spinlock_t reg_lock;
@@ -600,7 +602,7 @@ extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8
600/* PM Functions */ 602/* PM Functions */
601extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); 603extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
602extern int radeonfb_pci_resume(struct pci_dev *pdev); 604extern int radeonfb_pci_resume(struct pci_dev *pdev);
603extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk); 605extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep);
604extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); 606extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
605 607
606/* Monitor probe functions */ 608/* Monitor probe functions */