diff options
Diffstat (limited to 'drivers/video/aty')
-rw-r--r-- | drivers/video/aty/aty128fb.c | 70 | ||||
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 57 | ||||
-rw-r--r-- | drivers/video/aty/radeon_base.c | 19 | ||||
-rw-r--r-- | drivers/video/aty/radeon_pm.c | 146 | ||||
-rw-r--r-- | drivers/video/aty/radeonfb.h | 6 |
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); | |||
457 | static void wait_for_idle(struct aty128fb_par *par); | 456 | static void wait_for_idle(struct aty128fb_par *par); |
458 | static u32 depth_to_dst(u32 depth); | 457 | static u32 depth_to_dst(u32 depth); |
459 | 458 | ||
459 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | ||
460 | static 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 | ||
1704 | static struct backlight_properties aty128_bl_data; | 1693 | static struct backlight_properties aty128_bl_data; |
1705 | 1694 | ||
1695 | /* Call with fb_info->bl_mutex held */ | ||
1706 | static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | 1696 | static 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 | ||
1734 | static int aty128_bl_update_status(struct backlight_device *bd) | 1722 | /* Call with fb_info->bl_mutex held */ |
1723 | static 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 | ||
1776 | static 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 | |||
1787 | static int aty128_bl_get_brightness(struct backlight_device *bd) | 1789 | static 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 | ||
1801 | static 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 | |||
1799 | static void aty128_bl_init(struct aty128fb_par *par) | 1811 | static 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 | ||
2130 | static struct backlight_properties aty_bl_data; | 2130 | static struct backlight_properties aty_bl_data; |
2131 | 2131 | ||
2132 | /* Call with fb_info->bl_mutex held */ | ||
2132 | static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) | 2133 | static 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 | ||
2150 | static int aty_bl_update_status(struct backlight_device *bd) | 2149 | /* Call with fb_info->bl_mutex held */ |
2150 | static 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 | ||
2175 | static 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 | |||
2175 | static int aty_bl_get_brightness(struct backlight_device *bd) | 2188 | static 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 | ||
2200 | static 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 | |||
2187 | static void aty_bl_init(struct atyfb_par *par) | 2210 | static 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 |
268 | static int nomtrr = 0; | 267 | static int nomtrr = 0; |
269 | #endif | 268 | #endif |
269 | static int force_sleep; | ||
270 | static 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); | |||
2533 | MODULE_PARM_DESC(panel_yres, "int: set panel yres"); | 2540 | MODULE_PARM_DESC(panel_yres, "int: set panel yres"); |
2534 | module_param(mode_option, charp, 0); | 2541 | module_param(mode_option, charp, 0); |
2535 | MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | 2542 | MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); |
2543 | #if defined(CONFIG_PM) && defined(CONFIG_X86) | ||
2544 | module_param(force_sleep, bool, 0); | ||
2545 | MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware"); | ||
2546 | module_param(ignore_devlist, bool, 0); | ||
2547 | MODULE_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 | ||
30 | static 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) | ||
42 | struct 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 | |||
58 | static 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 | |||
92 | static 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) */ | ||
115 | static 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 | |||
30 | static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) | 123 | static 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 | ||
2716 | void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) | 2817 | void 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 | ||
2795 | void radeonfb_pm_exit(struct radeonfb_info *rinfo) | 2899 | void 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 | ||
276 | typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo); | ||
277 | |||
276 | struct radeonfb_info { | 278 | struct 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 */ |
601 | extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); | 603 | extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); |
602 | extern int radeonfb_pci_resume(struct pci_dev *pdev); | 604 | extern int radeonfb_pci_resume(struct pci_dev *pdev); |
603 | extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk); | 605 | extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep); |
604 | extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); | 606 | extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); |
605 | 607 | ||
606 | /* Monitor probe functions */ | 608 | /* Monitor probe functions */ |