aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hanselmann <linux-kernel@hansmi.ch>2006-07-10 07:44:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-10 16:24:20 -0400
commite01af0384f54023b4548b7742952da2ffcafd4cd (patch)
tree6ffd14821a0a1fedbf4430c5df7fa60822f4809f
parent58d383a6222d66be9483598c51bae34e7d3c2c37 (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.c31
-rw-r--r--drivers/macintosh/Kconfig5
-rw-r--r--drivers/video/aty/aty128fb.c66
-rw-r--r--drivers/video/aty/atyfb_base.c53
-rw-r--r--drivers/video/chipsfb.c3
-rw-r--r--drivers/video/nvidia/nv_backlight.c32
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nvidia.c11
-rw-r--r--drivers/video/riva/fbdev.c44
-rw-r--r--include/asm-powerpc/backlight.h12
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
18static void pmac_backlight_key_worker(void *data);
19static 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 */
25static int pmac_backlight_key_queued;
26
18/* Protect the pmac_backlight variable */ 27/* Protect the pmac_backlight variable */
19DEFINE_MUTEX(pmac_backlight_mutex); 28DEFINE_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
74static void pmac_backlight_key(int direction) 83static 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
100void pmac_backlight_key_up() 110void 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 */
105void 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
110int pmac_backlight_set_legacy_brightness(int brightness) 119int 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
170EXPORT_SYMBOL_GPL(pmac_backlight);
171EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
172EXPORT_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
114config PMAC_BACKLIGHT 114config 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);
455static void wait_for_fifo(u16 entries, struct aty128fb_par *par); 455static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
456static void wait_for_idle(struct aty128fb_par *par); 456static void wait_for_idle(struct aty128fb_par *par);
457static u32 depth_to_dst(u32 depth); 457static u32 depth_to_dst(u32 depth);
458static 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
1703static struct backlight_properties aty128_bl_data; 1690static struct backlight_properties aty128_bl_data;
1704 1691
1692/* Call with fb_info->bl_mutex held */
1705static int aty128_bl_get_level_brightness(struct aty128fb_par *par, 1693static 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
1733static int aty128_bl_update_status(struct backlight_device *bd) 1719/* Call with fb_info->bl_mutex held */
1720static 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
1773static 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
1786static int aty128_bl_get_brightness(struct backlight_device *bd) 1786static 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
1798static 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
1798static void aty128_bl_init(struct aty128fb_par *par) 1808static 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
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);
@@ -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
30static struct backlight_properties nvidia_bl_data; 31static struct backlight_properties nvidia_bl_data;
31 32
33/* Call with fb_info->bl_mutex held */
32static int nvidia_bl_get_level_brightness(struct nvidia_par *par, 34static 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
53static int nvidia_bl_update_status(struct backlight_device *bd) 53/* Call with fb_info->bl_mutex held */
54static 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
88static 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
87static int nvidia_bl_get_brightness(struct backlight_device *bd) 101static 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
113void 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
99void nvidia_bl_init(struct nvidia_par *par) 123void 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
69extern void nvidia_bl_init(struct nvidia_par *par); 69extern void nvidia_bl_init(struct nvidia_par *par);
70extern void nvidia_bl_exit(struct nvidia_par *par); 70extern void nvidia_bl_exit(struct nvidia_par *par);
71extern void nvidia_bl_set_power(struct fb_info *info, int power);
71#else 72#else
72static inline void nvidia_bl_init(struct nvidia_par *par) {} 73static inline void nvidia_bl_init(struct nvidia_par *par) {}
73static inline void nvidia_bl_exit(struct nvidia_par *par) {} 74static inline void nvidia_bl_exit(struct nvidia_par *par) {}
75static 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
281static struct backlight_properties riva_bl_data; 282static struct backlight_properties riva_bl_data;
282 283
284/* Call with fb_info->bl_mutex held */
283static int riva_bl_get_level_brightness(struct riva_par *par, 285static 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
304static int riva_bl_update_status(struct backlight_device *bd) 304/* Call with fb_info->bl_mutex held */
305static 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
330static 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
329static int riva_bl_get_brightness(struct backlight_device *bd) 343static 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
355static 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
341static void riva_bl_init(struct riva_par *par) 365static 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
419static inline void riva_bl_init(struct riva_par *par) {} 443static inline void riva_bl_init(struct riva_par *par) {}
420static inline void riva_bl_exit(struct riva_par *par) {} 444static inline void riva_bl_exit(struct riva_par *par) {}
445static 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 @@
16extern struct backlight_device *pmac_backlight; 16extern struct backlight_device *pmac_backlight;
17extern struct mutex pmac_backlight_mutex; 17extern struct mutex pmac_backlight_mutex;
18 18
19extern void pmac_backlight_calc_curve(struct fb_info*);
20extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); 19extern int pmac_backlight_curve_lookup(struct fb_info *info, int value);
21 20
22extern int pmac_has_backlight_type(const char *type); 21extern int pmac_has_backlight_type(const char *type);
23 22
24extern void pmac_backlight_key_up(void); 23extern void pmac_backlight_key(int direction);
25extern void pmac_backlight_key_down(void); 24static inline void pmac_backlight_key_up(void)
25{
26 pmac_backlight_key(0);
27}
28static inline void pmac_backlight_key_down(void)
29{
30 pmac_backlight_key(1);
31}
26 32
27extern int pmac_backlight_set_legacy_brightness(int brightness); 33extern int pmac_backlight_set_legacy_brightness(int brightness);
28extern int pmac_backlight_get_legacy_brightness(void); 34extern int pmac_backlight_get_legacy_brightness(void);