diff options
| author | Michael Hanselmann <linux-kernel@hansmi.ch> | 2006-07-10 07:44:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-10 16:24:20 -0400 |
| commit | e01af0384f54023b4548b7742952da2ffcafd4cd (patch) | |
| tree | 6ffd14821a0a1fedbf4430c5df7fa60822f4809f | |
| parent | 58d383a6222d66be9483598c51bae34e7d3c2c37 (diff) | |
[PATCH] powermac: Combined fixes for backlight code
This patch fixes several problems:
- pmac_backlight_key() is called under interrupt context, and therefore
can't use mutexes or semaphores, so defer the backlight level for
later, as it's not critical (original code by Aristeu S. Rozanski F.
<aris@valeta.org>).
- Add exports for functions that might be called from modules
- Fix Kconfig depdencies on PMAC_BACKLIGHT.
- Fix locking issues on calls from inside the driver (reported by
Aristeu S. Rozanski F., too)
- Fix wrong calculation of backlight values in some of the drivers
- Replace pmac_backlight_key_up/down by inline functions
[akpm@osdl.org: fix function prototypes]
Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Aristeu S. Rozanski F. <aris@valeta.org>
Acked-by: Rene Nussbaumer <linux-kernel@killerfox.forkbomb.ch>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/powerpc/platforms/powermac/backlight.c | 31 | ||||
| -rw-r--r-- | drivers/macintosh/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/video/aty/aty128fb.c | 66 | ||||
| -rw-r--r-- | drivers/video/aty/atyfb_base.c | 53 | ||||
| -rw-r--r-- | drivers/video/chipsfb.c | 3 | ||||
| -rw-r--r-- | drivers/video/nvidia/nv_backlight.c | 32 | ||||
| -rw-r--r-- | drivers/video/nvidia/nv_proto.h | 2 | ||||
| -rw-r--r-- | drivers/video/nvidia/nvidia.c | 11 | ||||
| -rw-r--r-- | drivers/video/riva/fbdev.c | 44 | ||||
| -rw-r--r-- | include/asm-powerpc/backlight.h | 12 |
10 files changed, 162 insertions, 97 deletions
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index 69f65e215a5c..74eed6b74cd6 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c | |||
| @@ -15,6 +15,15 @@ | |||
| 15 | 15 | ||
| 16 | #define OLD_BACKLIGHT_MAX 15 | 16 | #define OLD_BACKLIGHT_MAX 15 |
| 17 | 17 | ||
| 18 | static void pmac_backlight_key_worker(void *data); | ||
| 19 | static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL); | ||
| 20 | |||
| 21 | /* Although this variable is used in interrupt context, it makes no sense to | ||
| 22 | * protect it. No user is able to produce enough key events per second and | ||
| 23 | * notice the errors that might happen. | ||
| 24 | */ | ||
| 25 | static int pmac_backlight_key_queued; | ||
| 26 | |||
| 18 | /* Protect the pmac_backlight variable */ | 27 | /* Protect the pmac_backlight variable */ |
| 19 | DEFINE_MUTEX(pmac_backlight_mutex); | 28 | DEFINE_MUTEX(pmac_backlight_mutex); |
| 20 | 29 | ||
| @@ -71,7 +80,7 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value) | |||
| 71 | return level; | 80 | return level; |
| 72 | } | 81 | } |
| 73 | 82 | ||
| 74 | static void pmac_backlight_key(int direction) | 83 | static void pmac_backlight_key_worker(void *data) |
| 75 | { | 84 | { |
| 76 | mutex_lock(&pmac_backlight_mutex); | 85 | mutex_lock(&pmac_backlight_mutex); |
| 77 | if (pmac_backlight) { | 86 | if (pmac_backlight) { |
| @@ -82,7 +91,8 @@ static void pmac_backlight_key(int direction) | |||
| 82 | props = pmac_backlight->props; | 91 | props = pmac_backlight->props; |
| 83 | 92 | ||
| 84 | brightness = props->brightness + | 93 | brightness = props->brightness + |
| 85 | ((direction?-1:1) * (props->max_brightness / 15)); | 94 | ((pmac_backlight_key_queued?-1:1) * |
| 95 | (props->max_brightness / 15)); | ||
| 86 | 96 | ||
| 87 | if (brightness < 0) | 97 | if (brightness < 0) |
| 88 | brightness = 0; | 98 | brightness = 0; |
| @@ -97,14 +107,13 @@ static void pmac_backlight_key(int direction) | |||
| 97 | mutex_unlock(&pmac_backlight_mutex); | 107 | mutex_unlock(&pmac_backlight_mutex); |
| 98 | } | 108 | } |
| 99 | 109 | ||
| 100 | void pmac_backlight_key_up() | 110 | void pmac_backlight_key(int direction) |
| 101 | { | 111 | { |
| 102 | pmac_backlight_key(0); | 112 | /* we can receive multiple interrupts here, but the scheduled work |
| 103 | } | 113 | * will run only once, with the last value |
| 104 | 114 | */ | |
| 105 | void pmac_backlight_key_down() | 115 | pmac_backlight_key_queued = direction; |
| 106 | { | 116 | schedule_work(&pmac_backlight_key_work); |
| 107 | pmac_backlight_key(1); | ||
| 108 | } | 117 | } |
| 109 | 118 | ||
| 110 | int pmac_backlight_set_legacy_brightness(int brightness) | 119 | int pmac_backlight_set_legacy_brightness(int brightness) |
| @@ -157,3 +166,7 @@ int pmac_backlight_get_legacy_brightness() | |||
| 157 | 166 | ||
| 158 | return result; | 167 | return result; |
| 159 | } | 168 | } |
| 169 | |||
| 170 | EXPORT_SYMBOL_GPL(pmac_backlight); | ||
| 171 | EXPORT_SYMBOL_GPL(pmac_backlight_mutex); | ||
| 172 | EXPORT_SYMBOL_GPL(pmac_has_backlight_type); | ||
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 54f3f6b94efc..f5fe7fb4b3ad 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
| @@ -113,7 +113,10 @@ config PMAC_MEDIABAY | |||
| 113 | 113 | ||
| 114 | config PMAC_BACKLIGHT | 114 | config PMAC_BACKLIGHT |
| 115 | bool "Backlight control for LCD screens" | 115 | bool "Backlight control for LCD screens" |
| 116 | depends on ADB_PMU && (BROKEN || !PPC64) | 116 | depends on ADB_PMU && FB = y && (BROKEN || !PPC64) |
| 117 | select FB_BACKLIGHT | ||
| 118 | select BACKLIGHT_CLASS_DEVICE | ||
| 119 | select BACKLIGHT_LCD_SUPPORT | ||
| 117 | help | 120 | help |
| 118 | Say Y here to enable Macintosh specific extensions of the generic | 121 | Say Y here to enable Macintosh specific extensions of the generic |
| 119 | backlight code. With this enabled, the brightness keys on older | 122 | backlight code. With this enabled, the brightness keys on older |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 1006f125fcc7..c64a717e2d4b 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
| @@ -455,6 +455,7 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par); | |||
| 455 | static void wait_for_fifo(u16 entries, struct aty128fb_par *par); | 455 | static void wait_for_fifo(u16 entries, struct aty128fb_par *par); |
| 456 | static void wait_for_idle(struct aty128fb_par *par); | 456 | static void wait_for_idle(struct aty128fb_par *par); |
| 457 | static u32 depth_to_dst(u32 depth); | 457 | static u32 depth_to_dst(u32 depth); |
| 458 | static void aty128_bl_set_power(struct fb_info *info, int power); | ||
| 458 | 459 | ||
| 459 | #define BIOS_IN8(v) (readb(bios + (v))) | 460 | #define BIOS_IN8(v) (readb(bios + (v))) |
| 460 | #define BIOS_IN16(v) (readb(bios + (v)) | \ | 461 | #define BIOS_IN16(v) (readb(bios + (v)) | \ |
| @@ -1257,25 +1258,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) | |||
| 1257 | reg &= ~LVDS_DISPLAY_DIS; | 1258 | reg &= ~LVDS_DISPLAY_DIS; |
| 1258 | aty_st_le32(LVDS_GEN_CNTL, reg); | 1259 | aty_st_le32(LVDS_GEN_CNTL, reg); |
| 1259 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | 1260 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 1260 | mutex_lock(&info->bl_mutex); | 1261 | aty128_bl_set_power(info, FB_BLANK_UNBLANK); |
| 1261 | if (info->bl_dev) { | ||
| 1262 | down(&info->bl_dev->sem); | ||
| 1263 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1264 | up(&info->bl_dev->sem); | ||
| 1265 | } | ||
| 1266 | mutex_unlock(&info->bl_mutex); | ||
| 1267 | #endif | 1262 | #endif |
| 1268 | } else { | 1263 | } else { |
| 1269 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | 1264 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 1270 | mutex_lock(&info->bl_mutex); | 1265 | aty128_bl_set_power(info, FB_BLANK_POWERDOWN); |
| 1271 | if (info->bl_dev) { | ||
| 1272 | down(&info->bl_dev->sem); | ||
| 1273 | info->bl_dev->props->brightness = 0; | ||
| 1274 | info->bl_dev->props->power = FB_BLANK_POWERDOWN; | ||
| 1275 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1276 | up(&info->bl_dev->sem); | ||
| 1277 | } | ||
| 1278 | mutex_unlock(&info->bl_mutex); | ||
| 1279 | #endif | 1266 | #endif |
| 1280 | reg = aty_ld_le32(LVDS_GEN_CNTL); | 1267 | reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1281 | reg |= LVDS_DISPLAY_DIS; | 1268 | reg |= LVDS_DISPLAY_DIS; |
| @@ -1702,6 +1689,7 @@ static int __devinit aty128fb_setup(char *options) | |||
| 1702 | 1689 | ||
| 1703 | static struct backlight_properties aty128_bl_data; | 1690 | static struct backlight_properties aty128_bl_data; |
| 1704 | 1691 | ||
| 1692 | /* Call with fb_info->bl_mutex held */ | ||
| 1705 | static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | 1693 | static int aty128_bl_get_level_brightness(struct aty128fb_par *par, |
| 1706 | int level) | 1694 | int level) |
| 1707 | { | 1695 | { |
| @@ -1709,10 +1697,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | |||
| 1709 | int atylevel; | 1697 | int atylevel; |
| 1710 | 1698 | ||
| 1711 | /* Get and convert the value */ | 1699 | /* Get and convert the value */ |
| 1712 | mutex_lock(&info->bl_mutex); | ||
| 1713 | atylevel = MAX_LEVEL - | 1700 | atylevel = MAX_LEVEL - |
| 1714 | (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); | 1701 | (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); |
| 1715 | mutex_unlock(&info->bl_mutex); | ||
| 1716 | 1702 | ||
| 1717 | if (atylevel < 0) | 1703 | if (atylevel < 0) |
| 1718 | atylevel = 0; | 1704 | atylevel = 0; |
| @@ -1730,7 +1716,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | |||
| 1730 | /* That one prevents proper CRT output with LCD off */ | 1716 | /* That one prevents proper CRT output with LCD off */ |
| 1731 | #undef BACKLIGHT_DAC_OFF | 1717 | #undef BACKLIGHT_DAC_OFF |
| 1732 | 1718 | ||
| 1733 | static int aty128_bl_update_status(struct backlight_device *bd) | 1719 | /* Call with fb_info->bl_mutex held */ |
| 1720 | static int __aty128_bl_update_status(struct backlight_device *bd) | ||
| 1734 | { | 1721 | { |
| 1735 | struct aty128fb_par *par = class_get_devdata(&bd->class_dev); | 1722 | struct aty128fb_par *par = class_get_devdata(&bd->class_dev); |
| 1736 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); | 1723 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); |
| @@ -1783,6 +1770,19 @@ static int aty128_bl_update_status(struct backlight_device *bd) | |||
| 1783 | return 0; | 1770 | return 0; |
| 1784 | } | 1771 | } |
| 1785 | 1772 | ||
| 1773 | static int aty128_bl_update_status(struct backlight_device *bd) | ||
| 1774 | { | ||
| 1775 | struct aty128fb_par *par = class_get_devdata(&bd->class_dev); | ||
| 1776 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 1777 | int ret; | ||
| 1778 | |||
| 1779 | mutex_lock(&info->bl_mutex); | ||
| 1780 | ret = __aty128_bl_update_status(bd); | ||
| 1781 | mutex_unlock(&info->bl_mutex); | ||
| 1782 | |||
| 1783 | return ret; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static int aty128_bl_get_brightness(struct backlight_device *bd) | 1786 | static int aty128_bl_get_brightness(struct backlight_device *bd) |
| 1787 | { | 1787 | { |
| 1788 | return bd->props->brightness; | 1788 | return bd->props->brightness; |
| @@ -1795,6 +1795,16 @@ static struct backlight_properties aty128_bl_data = { | |||
| 1795 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | 1795 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
| 1796 | }; | 1796 | }; |
| 1797 | 1797 | ||
| 1798 | static void aty128_bl_set_power(struct fb_info *info, int power) | ||
| 1799 | { | ||
| 1800 | mutex_lock(&info->bl_mutex); | ||
| 1801 | up(&info->bl_dev->sem); | ||
| 1802 | info->bl_dev->props->power = power; | ||
| 1803 | __aty128_bl_update_status(info->bl_dev); | ||
| 1804 | down(&info->bl_dev->sem); | ||
| 1805 | mutex_unlock(&info->bl_mutex); | ||
| 1806 | } | ||
| 1807 | |||
| 1798 | static void aty128_bl_init(struct aty128fb_par *par) | 1808 | static void aty128_bl_init(struct aty128fb_par *par) |
| 1799 | { | 1809 | { |
| 1800 | struct fb_info *info = pci_get_drvdata(par->pdev); | 1810 | struct fb_info *info = pci_get_drvdata(par->pdev); |
| @@ -2197,12 +2207,8 @@ static int aty128fb_blank(int blank, struct fb_info *fb) | |||
| 2197 | return 0; | 2207 | return 0; |
| 2198 | 2208 | ||
| 2199 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | 2209 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 2200 | if (machine_is(powermac) && blank) { | 2210 | if (machine_is(powermac) && blank) |
| 2201 | down(&fb->bl_dev->sem); | 2211 | aty128_bl_set_power(fb, FB_BLANK_POWERDOWN); |
| 2202 | fb->bl_dev->props->power = FB_BLANK_POWERDOWN; | ||
| 2203 | fb->bl_dev->props->update_status(fb->bl_dev); | ||
| 2204 | up(&fb->bl_dev->sem); | ||
| 2205 | } | ||
| 2206 | #endif | 2212 | #endif |
| 2207 | 2213 | ||
| 2208 | if (blank & FB_BLANK_VSYNC_SUSPEND) | 2214 | if (blank & FB_BLANK_VSYNC_SUSPEND) |
| @@ -2218,14 +2224,12 @@ static int aty128fb_blank(int blank, struct fb_info *fb) | |||
| 2218 | aty128_set_crt_enable(par, par->crt_on && !blank); | 2224 | aty128_set_crt_enable(par, par->crt_on && !blank); |
| 2219 | aty128_set_lcd_enable(par, par->lcd_on && !blank); | 2225 | aty128_set_lcd_enable(par, par->lcd_on && !blank); |
| 2220 | } | 2226 | } |
| 2227 | |||
| 2221 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | 2228 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 2222 | if (machine_is(powermac) && !blank) { | 2229 | if (machine_is(powermac) && !blank) |
| 2223 | down(&fb->bl_dev->sem); | 2230 | aty128_bl_set_power(fb, FB_BLANK_UNBLANK); |
| 2224 | fb->bl_dev->props->power = FB_BLANK_UNBLANK; | ||
| 2225 | fb->bl_dev->props->update_status(fb->bl_dev); | ||
| 2226 | up(&fb->bl_dev->sem); | ||
| 2227 | } | ||
| 2228 | #endif | 2231 | #endif |
| 2232 | |||
| 2229 | return 0; | 2233 | return 0; |
| 2230 | } | 2234 | } |
| 2231 | 2235 | ||
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 0c9706746d79..1507d19f481f 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); |
| @@ -2790,16 +2813,8 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
| 2790 | return 0; | 2813 | return 0; |
| 2791 | 2814 | ||
| 2792 | #ifdef CONFIG_PMAC_BACKLIGHT | 2815 | #ifdef CONFIG_PMAC_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)) { |
| @@ -2830,16 +2845,8 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
| 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_PMAC_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/chipsfb.c b/drivers/video/chipsfb.c index eba9d93ae360..73cb426bf2d7 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c | |||
| @@ -149,12 +149,11 @@ static int chipsfb_blank(int blank, struct fb_info *info) | |||
| 149 | mutex_lock(&pmac_backlight_mutex); | 149 | mutex_lock(&pmac_backlight_mutex); |
| 150 | 150 | ||
| 151 | if (pmac_backlight) { | 151 | if (pmac_backlight) { |
| 152 | down(&pmac_backlight->sem); | ||
| 153 | |||
| 154 | /* used to disable backlight only for blank > 1, but it seems | 152 | /* used to disable backlight only for blank > 1, but it seems |
| 155 | * useful at blank = 1 too (saves battery, extends backlight | 153 | * useful at blank = 1 too (saves battery, extends backlight |
| 156 | * life) | 154 | * life) |
| 157 | */ | 155 | */ |
| 156 | down(&pmac_backlight->sem); | ||
| 158 | if (blank) | 157 | if (blank) |
| 159 | pmac_backlight->props->power = FB_BLANK_POWERDOWN; | 158 | pmac_backlight->props->power = FB_BLANK_POWERDOWN; |
| 160 | else | 159 | else |
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index 1c1c10c699c5..b45f577094ac 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c | |||
| @@ -26,9 +26,11 @@ | |||
| 26 | */ | 26 | */ |
| 27 | #define MIN_LEVEL 0x158 | 27 | #define MIN_LEVEL 0x158 |
| 28 | #define MAX_LEVEL 0x534 | 28 | #define MAX_LEVEL 0x534 |
| 29 | #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) | ||
| 29 | 30 | ||
| 30 | static struct backlight_properties nvidia_bl_data; | 31 | static struct backlight_properties nvidia_bl_data; |
| 31 | 32 | ||
| 33 | /* Call with fb_info->bl_mutex held */ | ||
| 32 | static int nvidia_bl_get_level_brightness(struct nvidia_par *par, | 34 | static int nvidia_bl_get_level_brightness(struct nvidia_par *par, |
| 33 | int level) | 35 | int level) |
| 34 | { | 36 | { |
| @@ -36,9 +38,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, | |||
| 36 | int nlevel; | 38 | int nlevel; |
| 37 | 39 | ||
| 38 | /* Get and convert the value */ | 40 | /* Get and convert the value */ |
| 39 | mutex_lock(&info->bl_mutex); | 41 | nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; |
| 40 | nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; | ||
| 41 | mutex_unlock(&info->bl_mutex); | ||
| 42 | 42 | ||
| 43 | if (nlevel < 0) | 43 | if (nlevel < 0) |
| 44 | nlevel = 0; | 44 | nlevel = 0; |
| @@ -50,7 +50,8 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, | |||
| 50 | return nlevel; | 50 | return nlevel; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | static int nvidia_bl_update_status(struct backlight_device *bd) | 53 | /* Call with fb_info->bl_mutex held */ |
| 54 | static int __nvidia_bl_update_status(struct backlight_device *bd) | ||
| 54 | { | 55 | { |
| 55 | struct nvidia_par *par = class_get_devdata(&bd->class_dev); | 56 | struct nvidia_par *par = class_get_devdata(&bd->class_dev); |
| 56 | u32 tmp_pcrt, tmp_pmc, fpcontrol; | 57 | u32 tmp_pcrt, tmp_pmc, fpcontrol; |
| @@ -84,6 +85,19 @@ static int nvidia_bl_update_status(struct backlight_device *bd) | |||
| 84 | return 0; | 85 | return 0; |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 88 | static int nvidia_bl_update_status(struct backlight_device *bd) | ||
| 89 | { | ||
| 90 | struct nvidia_par *par = class_get_devdata(&bd->class_dev); | ||
| 91 | struct fb_info *info = pci_get_drvdata(par->pci_dev); | ||
| 92 | int ret; | ||
| 93 | |||
| 94 | mutex_lock(&info->bl_mutex); | ||
| 95 | ret = __nvidia_bl_update_status(bd); | ||
| 96 | mutex_unlock(&info->bl_mutex); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 87 | static int nvidia_bl_get_brightness(struct backlight_device *bd) | 101 | static int nvidia_bl_get_brightness(struct backlight_device *bd) |
| 88 | { | 102 | { |
| 89 | return bd->props->brightness; | 103 | return bd->props->brightness; |
| @@ -96,6 +110,16 @@ static struct backlight_properties nvidia_bl_data = { | |||
| 96 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | 110 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
| 97 | }; | 111 | }; |
| 98 | 112 | ||
| 113 | void nvidia_bl_set_power(struct fb_info *info, int power) | ||
| 114 | { | ||
| 115 | mutex_lock(&info->bl_mutex); | ||
| 116 | up(&info->bl_dev->sem); | ||
| 117 | info->bl_dev->props->power = power; | ||
| 118 | __nvidia_bl_update_status(info->bl_dev); | ||
| 119 | down(&info->bl_dev->sem); | ||
| 120 | mutex_unlock(&info->bl_mutex); | ||
| 121 | } | ||
| 122 | |||
| 99 | void nvidia_bl_init(struct nvidia_par *par) | 123 | void nvidia_bl_init(struct nvidia_par *par) |
| 100 | { | 124 | { |
| 101 | struct fb_info *info = pci_get_drvdata(par->pci_dev); | 125 | struct fb_info *info = pci_get_drvdata(par->pci_dev); |
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 6fba656cd56b..861271017655 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
| @@ -68,9 +68,11 @@ extern u8 byte_rev[256]; | |||
| 68 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT | 68 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT |
| 69 | extern void nvidia_bl_init(struct nvidia_par *par); | 69 | extern void nvidia_bl_init(struct nvidia_par *par); |
| 70 | extern void nvidia_bl_exit(struct nvidia_par *par); | 70 | extern void nvidia_bl_exit(struct nvidia_par *par); |
| 71 | extern void nvidia_bl_set_power(struct fb_info *info, int power); | ||
| 71 | #else | 72 | #else |
| 72 | static inline void nvidia_bl_init(struct nvidia_par *par) {} | 73 | static inline void nvidia_bl_init(struct nvidia_par *par) {} |
| 73 | static inline void nvidia_bl_exit(struct nvidia_par *par) {} | 74 | static inline void nvidia_bl_exit(struct nvidia_par *par) {} |
| 75 | static inline void nvidia_bl_set_power(struct fb_info *info, int power) {} | ||
| 74 | #endif | 76 | #endif |
| 75 | 77 | ||
| 76 | #endif /* __NV_PROTO_H__ */ | 78 | #endif /* __NV_PROTO_H__ */ |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index ef58c3825501..9f2066f0745a 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
| @@ -932,16 +932,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info) | |||
| 932 | NVWriteSeq(par, 0x01, tmp); | 932 | NVWriteSeq(par, 0x01, tmp); |
| 933 | NVWriteCrtc(par, 0x1a, vesa); | 933 | NVWriteCrtc(par, 0x1a, vesa); |
| 934 | 934 | ||
| 935 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT | 935 | nvidia_bl_set_power(info, blank); |
| 936 | mutex_lock(&info->bl_mutex); | ||
| 937 | if (info->bl_dev) { | ||
| 938 | down(&info->bl_dev->sem); | ||
| 939 | info->bl_dev->props->power = blank; | ||
| 940 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 941 | up(&info->bl_dev->sem); | ||
| 942 | } | ||
| 943 | mutex_unlock(&info->bl_mutex); | ||
| 944 | #endif | ||
| 945 | 936 | ||
| 946 | NVTRACE_LEAVE(); | 937 | NVTRACE_LEAVE(); |
| 947 | 938 | ||
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index baf494cecc10..33dddbae5420 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
| @@ -277,9 +277,11 @@ static const struct riva_regs reg_template = { | |||
| 277 | */ | 277 | */ |
| 278 | #define MIN_LEVEL 0x158 | 278 | #define MIN_LEVEL 0x158 |
| 279 | #define MAX_LEVEL 0x534 | 279 | #define MAX_LEVEL 0x534 |
| 280 | #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) | ||
| 280 | 281 | ||
| 281 | static struct backlight_properties riva_bl_data; | 282 | static struct backlight_properties riva_bl_data; |
| 282 | 283 | ||
| 284 | /* Call with fb_info->bl_mutex held */ | ||
| 283 | static int riva_bl_get_level_brightness(struct riva_par *par, | 285 | static int riva_bl_get_level_brightness(struct riva_par *par, |
| 284 | int level) | 286 | int level) |
| 285 | { | 287 | { |
| @@ -287,9 +289,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par, | |||
| 287 | int nlevel; | 289 | int nlevel; |
| 288 | 290 | ||
| 289 | /* Get and convert the value */ | 291 | /* Get and convert the value */ |
| 290 | mutex_lock(&info->bl_mutex); | 292 | nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; |
| 291 | nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; | ||
| 292 | mutex_unlock(&info->bl_mutex); | ||
| 293 | 293 | ||
| 294 | if (nlevel < 0) | 294 | if (nlevel < 0) |
| 295 | nlevel = 0; | 295 | nlevel = 0; |
| @@ -301,7 +301,8 @@ static int riva_bl_get_level_brightness(struct riva_par *par, | |||
| 301 | return nlevel; | 301 | return nlevel; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | static int riva_bl_update_status(struct backlight_device *bd) | 304 | /* Call with fb_info->bl_mutex held */ |
| 305 | static int __riva_bl_update_status(struct backlight_device *bd) | ||
| 305 | { | 306 | { |
| 306 | struct riva_par *par = class_get_devdata(&bd->class_dev); | 307 | struct riva_par *par = class_get_devdata(&bd->class_dev); |
| 307 | U032 tmp_pcrt, tmp_pmc; | 308 | U032 tmp_pcrt, tmp_pmc; |
| @@ -326,6 +327,19 @@ static int riva_bl_update_status(struct backlight_device *bd) | |||
| 326 | return 0; | 327 | return 0; |
| 327 | } | 328 | } |
| 328 | 329 | ||
| 330 | static int riva_bl_update_status(struct backlight_device *bd) | ||
| 331 | { | ||
| 332 | struct riva_par *par = class_get_devdata(&bd->class_dev); | ||
| 333 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 334 | int ret; | ||
| 335 | |||
| 336 | mutex_lock(&info->bl_mutex); | ||
| 337 | ret = __riva_bl_update_status(bd); | ||
| 338 | mutex_unlock(&info->bl_mutex); | ||
| 339 | |||
| 340 | return ret; | ||
| 341 | } | ||
| 342 | |||
| 329 | static int riva_bl_get_brightness(struct backlight_device *bd) | 343 | static int riva_bl_get_brightness(struct backlight_device *bd) |
| 330 | { | 344 | { |
| 331 | return bd->props->brightness; | 345 | return bd->props->brightness; |
| @@ -338,6 +352,16 @@ static struct backlight_properties riva_bl_data = { | |||
| 338 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | 352 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
| 339 | }; | 353 | }; |
| 340 | 354 | ||
| 355 | static void riva_bl_set_power(struct fb_info *info, int power) | ||
| 356 | { | ||
| 357 | mutex_lock(&info->bl_mutex); | ||
| 358 | up(&info->bl_dev->sem); | ||
| 359 | info->bl_dev->props->power = power; | ||
| 360 | __riva_bl_update_status(info->bl_dev); | ||
| 361 | down(&info->bl_dev->sem); | ||
| 362 | mutex_unlock(&info->bl_mutex); | ||
| 363 | } | ||
| 364 | |||
| 341 | static void riva_bl_init(struct riva_par *par) | 365 | static void riva_bl_init(struct riva_par *par) |
| 342 | { | 366 | { |
| 343 | struct fb_info *info = pci_get_drvdata(par->pdev); | 367 | struct fb_info *info = pci_get_drvdata(par->pdev); |
| @@ -418,6 +442,7 @@ static void riva_bl_exit(struct riva_par *par) | |||
| 418 | #else | 442 | #else |
| 419 | static inline void riva_bl_init(struct riva_par *par) {} | 443 | static inline void riva_bl_init(struct riva_par *par) {} |
| 420 | static inline void riva_bl_exit(struct riva_par *par) {} | 444 | static inline void riva_bl_exit(struct riva_par *par) {} |
| 445 | static inline void riva_bl_set_power(struct fb_info *info, int power) {} | ||
| 421 | #endif /* CONFIG_FB_RIVA_BACKLIGHT */ | 446 | #endif /* CONFIG_FB_RIVA_BACKLIGHT */ |
| 422 | 447 | ||
| 423 | /* ------------------------------------------------------------------------- * | 448 | /* ------------------------------------------------------------------------- * |
| @@ -1336,16 +1361,7 @@ static int rivafb_blank(int blank, struct fb_info *info) | |||
| 1336 | SEQout(par, 0x01, tmp); | 1361 | SEQout(par, 0x01, tmp); |
| 1337 | CRTCout(par, 0x1a, vesa); | 1362 | CRTCout(par, 0x1a, vesa); |
| 1338 | 1363 | ||
| 1339 | #ifdef CONFIG_FB_RIVA_BACKLIGHT | 1364 | riva_bl_set_power(info, blank); |
| 1340 | mutex_lock(&info->bl_mutex); | ||
| 1341 | if (info->bl_dev) { | ||
| 1342 | down(&info->bl_dev->sem); | ||
| 1343 | info->bl_dev->props->power = blank; | ||
| 1344 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1345 | up(&info->bl_dev->sem); | ||
| 1346 | } | ||
| 1347 | mutex_unlock(&info->bl_mutex); | ||
| 1348 | #endif | ||
| 1349 | 1365 | ||
| 1350 | NVTRACE_LEAVE(); | 1366 | NVTRACE_LEAVE(); |
| 1351 | 1367 | ||
diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h index a5e9e656e332..58d4b6f8d827 100644 --- a/include/asm-powerpc/backlight.h +++ b/include/asm-powerpc/backlight.h | |||
| @@ -16,13 +16,19 @@ | |||
| 16 | extern struct backlight_device *pmac_backlight; | 16 | extern struct backlight_device *pmac_backlight; |
| 17 | extern struct mutex pmac_backlight_mutex; | 17 | extern struct mutex pmac_backlight_mutex; |
| 18 | 18 | ||
| 19 | extern void pmac_backlight_calc_curve(struct fb_info*); | ||
| 20 | extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); | 19 | extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); |
| 21 | 20 | ||
| 22 | extern int pmac_has_backlight_type(const char *type); | 21 | extern int pmac_has_backlight_type(const char *type); |
| 23 | 22 | ||
| 24 | extern void pmac_backlight_key_up(void); | 23 | extern void pmac_backlight_key(int direction); |
| 25 | extern void pmac_backlight_key_down(void); | 24 | static inline void pmac_backlight_key_up(void) |
| 25 | { | ||
| 26 | pmac_backlight_key(0); | ||
| 27 | } | ||
| 28 | static inline void pmac_backlight_key_down(void) | ||
| 29 | { | ||
| 30 | pmac_backlight_key(1); | ||
| 31 | } | ||
| 26 | 32 | ||
| 27 | extern int pmac_backlight_set_legacy_brightness(int brightness); | 33 | extern int pmac_backlight_set_legacy_brightness(int brightness); |
| 28 | extern int pmac_backlight_get_legacy_brightness(void); | 34 | extern int pmac_backlight_get_legacy_brightness(void); |
