diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-09-01 00:27:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-01 14:39:09 -0400 |
commit | d565dd3b0824b67a8442df4de83cc44f7c726fc9 (patch) | |
tree | efe10d3e6355353a3ffd416a873d609119d9fbd9 /drivers | |
parent | 0b1d647a02c5a1b67d45287eeb6cb3b2219c41c3 (diff) |
[PATCH] powerpc: More via-pmu backlight fixes
The via-pmu backlight code (introduced in 2.6.18) has various design issues
causing crashes on machines using it like the old Wallstreet powerbook
(Michael, the author, never managed to test on these and I just got my hand
on one of those old beasts).
This fixes them by no longer trying to hijack the backlight device of the
frontmost framebuffer (causing that framebuffer to crash) but having it's
own local bits instead. Might look weird but it's better that way on those
old machines, at least as a last-minute fix for 2.6.18. We might rework
the whole thing later. This patch also changes the way it gets notified of
sleep and wakeup in order to properly shut the backlight down on sleep and
bring it back on wakeup.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/macintosh/via-pmu-backlight.c | 95 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu.c | 12 |
2 files changed, 57 insertions, 50 deletions
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index d3f8d75bcbb4..4397fac55ba0 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c | |||
@@ -18,17 +18,48 @@ | |||
18 | static struct backlight_properties pmu_backlight_data; | 18 | static struct backlight_properties pmu_backlight_data; |
19 | static spinlock_t pmu_backlight_lock; | 19 | static spinlock_t pmu_backlight_lock; |
20 | static int sleeping; | 20 | static int sleeping; |
21 | static u8 bl_curve[FB_BACKLIGHT_LEVELS]; | ||
21 | 22 | ||
22 | static int pmu_backlight_get_level_brightness(struct fb_info *info, | 23 | static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) |
23 | int level) | 24 | { |
25 | unsigned int i, flat, count, range = (max - min); | ||
26 | |||
27 | bl_curve[0] = off; | ||
28 | |||
29 | for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) | ||
30 | bl_curve[flat] = min; | ||
31 | |||
32 | count = FB_BACKLIGHT_LEVELS * 15 / 16; | ||
33 | for (i = 0; i < count; ++i) | ||
34 | bl_curve[flat + i] = min + (range * (i + 1) / count); | ||
35 | } | ||
36 | |||
37 | static int pmu_backlight_curve_lookup(int value) | ||
38 | { | ||
39 | int level = (FB_BACKLIGHT_LEVELS - 1); | ||
40 | int i, max = 0; | ||
41 | |||
42 | /* Look for biggest value */ | ||
43 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) | ||
44 | max = max((int)bl_curve[i], max); | ||
45 | |||
46 | /* Look for nearest value */ | ||
47 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { | ||
48 | int diff = abs(bl_curve[i] - value); | ||
49 | if (diff < max) { | ||
50 | max = diff; | ||
51 | level = i; | ||
52 | } | ||
53 | } | ||
54 | return level; | ||
55 | } | ||
56 | |||
57 | static int pmu_backlight_get_level_brightness(int level) | ||
24 | { | 58 | { |
25 | int pmulevel; | 59 | int pmulevel; |
26 | 60 | ||
27 | /* Get and convert the value */ | 61 | /* Get and convert the value */ |
28 | mutex_lock(&info->bl_mutex); | 62 | pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; |
29 | pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; | ||
30 | mutex_unlock(&info->bl_mutex); | ||
31 | |||
32 | if (pmulevel < 0) | 63 | if (pmulevel < 0) |
33 | pmulevel = 0; | 64 | pmulevel = 0; |
34 | else if (pmulevel > MAX_PMU_LEVEL) | 65 | else if (pmulevel > MAX_PMU_LEVEL) |
@@ -39,7 +70,6 @@ static int pmu_backlight_get_level_brightness(struct fb_info *info, | |||
39 | 70 | ||
40 | static int pmu_backlight_update_status(struct backlight_device *bd) | 71 | static int pmu_backlight_update_status(struct backlight_device *bd) |
41 | { | 72 | { |
42 | struct fb_info *info = class_get_devdata(&bd->class_dev); | ||
43 | struct adb_request req; | 73 | struct adb_request req; |
44 | unsigned long flags; | 74 | unsigned long flags; |
45 | int level = bd->props->brightness; | 75 | int level = bd->props->brightness; |
@@ -55,7 +85,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd) | |||
55 | level = 0; | 85 | level = 0; |
56 | 86 | ||
57 | if (level > 0) { | 87 | if (level > 0) { |
58 | int pmulevel = pmu_backlight_get_level_brightness(info, level); | 88 | int pmulevel = pmu_backlight_get_level_brightness(level); |
59 | 89 | ||
60 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); | 90 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); |
61 | pmu_wait_complete(&req); | 91 | pmu_wait_complete(&req); |
@@ -88,35 +118,19 @@ static struct backlight_properties pmu_backlight_data = { | |||
88 | }; | 118 | }; |
89 | 119 | ||
90 | #ifdef CONFIG_PM | 120 | #ifdef CONFIG_PM |
91 | static int pmu_backlight_sleep_call(struct pmu_sleep_notifier *self, int when) | 121 | void pmu_backlight_set_sleep(int sleep) |
92 | { | 122 | { |
93 | unsigned long flags; | 123 | unsigned long flags; |
94 | 124 | ||
95 | spin_lock_irqsave(&pmu_backlight_lock, flags); | 125 | spin_lock_irqsave(&pmu_backlight_lock, flags); |
96 | 126 | sleeping = sleep; | |
97 | switch (when) { | ||
98 | case PBOOK_SLEEP_REQUEST: | ||
99 | sleeping = 1; | ||
100 | break; | ||
101 | case PBOOK_WAKE: | ||
102 | sleeping = 0; | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | spin_unlock_irqrestore(&pmu_backlight_lock, flags); | 127 | spin_unlock_irqrestore(&pmu_backlight_lock, flags); |
107 | |||
108 | return PBOOK_SLEEP_OK; | ||
109 | } | 128 | } |
110 | 129 | #endif /* CONFIG_PM */ | |
111 | static struct pmu_sleep_notifier pmu_backlight_sleep_notif = { | ||
112 | .notifier_call = pmu_backlight_sleep_call, | ||
113 | }; | ||
114 | #endif | ||
115 | 130 | ||
116 | void __init pmu_backlight_init() | 131 | void __init pmu_backlight_init() |
117 | { | 132 | { |
118 | struct backlight_device *bd; | 133 | struct backlight_device *bd; |
119 | struct fb_info *info; | ||
120 | char name[10]; | 134 | char name[10]; |
121 | int level, autosave; | 135 | int level, autosave; |
122 | 136 | ||
@@ -131,27 +145,14 @@ void __init pmu_backlight_init() | |||
131 | !machine_is_compatible("PowerBook1,1")) | 145 | !machine_is_compatible("PowerBook1,1")) |
132 | return; | 146 | return; |
133 | 147 | ||
134 | /* Actually, this is a hack, but I don't know of a better way | 148 | snprintf(name, sizeof(name), "pmubl"); |
135 | * to get the first framebuffer device. | ||
136 | */ | ||
137 | info = registered_fb[0]; | ||
138 | if (!info) { | ||
139 | printk("pmubl: No framebuffer found\n"); | ||
140 | goto error; | ||
141 | } | ||
142 | |||
143 | snprintf(name, sizeof(name), "pmubl%d", info->node); | ||
144 | 149 | ||
145 | bd = backlight_device_register(name, info, &pmu_backlight_data); | 150 | bd = backlight_device_register(name, NULL, &pmu_backlight_data); |
146 | if (IS_ERR(bd)) { | 151 | if (IS_ERR(bd)) { |
147 | printk("pmubl: Backlight registration failed\n"); | 152 | printk("pmubl: Backlight registration failed\n"); |
148 | goto error; | 153 | goto error; |
149 | } | 154 | } |
150 | 155 | pmu_backlight_init_curve(0x7F, 0x46, 0x0E); | |
151 | mutex_lock(&info->bl_mutex); | ||
152 | info->bl_dev = bd; | ||
153 | fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); | ||
154 | mutex_unlock(&info->bl_mutex); | ||
155 | 156 | ||
156 | level = pmu_backlight_data.max_brightness; | 157 | level = pmu_backlight_data.max_brightness; |
157 | 158 | ||
@@ -161,11 +162,9 @@ void __init pmu_backlight_init() | |||
161 | pmu_request(&req, NULL, 2, 0xd9, 0); | 162 | pmu_request(&req, NULL, 2, 0xd9, 0); |
162 | pmu_wait_complete(&req); | 163 | pmu_wait_complete(&req); |
163 | 164 | ||
164 | mutex_lock(&info->bl_mutex); | 165 | level = pmu_backlight_curve_lookup( |
165 | level = pmac_backlight_curve_lookup(info, | ||
166 | (req.reply[0] >> 4) * | 166 | (req.reply[0] >> 4) * |
167 | pmu_backlight_data.max_brightness / 15); | 167 | pmu_backlight_data.max_brightness / 15); |
168 | mutex_unlock(&info->bl_mutex); | ||
169 | } | 168 | } |
170 | 169 | ||
171 | up(&bd->sem); | 170 | up(&bd->sem); |
@@ -179,10 +178,6 @@ void __init pmu_backlight_init() | |||
179 | pmac_backlight = bd; | 178 | pmac_backlight = bd; |
180 | mutex_unlock(&pmac_backlight_mutex); | 179 | mutex_unlock(&pmac_backlight_mutex); |
181 | 180 | ||
182 | #ifdef CONFIG_PM | ||
183 | pmu_register_sleep_notifier(&pmu_backlight_sleep_notif); | ||
184 | #endif | ||
185 | |||
186 | printk("pmubl: Backlight initialized (%s)\n", name); | 181 | printk("pmubl: Backlight initialized (%s)\n", name); |
187 | 182 | ||
188 | return; | 183 | return; |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index ea386801e215..14610a63f580 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -1995,6 +1995,8 @@ restore_via_state(void) | |||
1995 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); | 1995 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); |
1996 | } | 1996 | } |
1997 | 1997 | ||
1998 | extern void pmu_backlight_set_sleep(int sleep); | ||
1999 | |||
1998 | static int | 2000 | static int |
1999 | pmac_suspend_devices(void) | 2001 | pmac_suspend_devices(void) |
2000 | { | 2002 | { |
@@ -2032,6 +2034,11 @@ pmac_suspend_devices(void) | |||
2032 | return -EBUSY; | 2034 | return -EBUSY; |
2033 | } | 2035 | } |
2034 | 2036 | ||
2037 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2038 | /* Tell backlight code not to muck around with the chip anymore */ | ||
2039 | pmu_backlight_set_sleep(1); | ||
2040 | #endif | ||
2041 | |||
2035 | /* Call platform functions marked "on sleep" */ | 2042 | /* Call platform functions marked "on sleep" */ |
2036 | pmac_pfunc_i2c_suspend(); | 2043 | pmac_pfunc_i2c_suspend(); |
2037 | pmac_pfunc_base_suspend(); | 2044 | pmac_pfunc_base_suspend(); |
@@ -2090,6 +2097,11 @@ pmac_wakeup_devices(void) | |||
2090 | { | 2097 | { |
2091 | mdelay(100); | 2098 | mdelay(100); |
2092 | 2099 | ||
2100 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2101 | /* Tell backlight code it can use the chip again */ | ||
2102 | pmu_backlight_set_sleep(0); | ||
2103 | #endif | ||
2104 | |||
2093 | /* Power back up system devices (including the PIC) */ | 2105 | /* Power back up system devices (including the PIC) */ |
2094 | device_power_up(); | 2106 | device_power_up(); |
2095 | 2107 | ||