diff options
author | Michael Hanselmann <linux-kernel@hansmi.ch> | 2006-06-25 08:47:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:00:59 -0400 |
commit | 5474c120aafe78ca54bf272f7a01107c42da2b21 (patch) | |
tree | c1b002a27703ce92c816bfb9844752186e33d403 /drivers/video/riva/fbdev.c | |
parent | 17660bdd5c1f1a165273c1a59cb5b87670a81cc4 (diff) |
[PATCH] Rewritten backlight infrastructure for portable Apple computers
This patch contains a total rewrite of the backlight infrastructure for
portable Apple computers. Backward compatibility is retained. A sysfs
interface allows userland to control the brightness with more steps than
before. Userland is allowed to upload a brightness curve for different
monitors, similar to Mac OS X.
[akpm@osdl.org: add needed exports]
Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Richard Purdie <rpurdie@rpsys.net>
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/video/riva/fbdev.c')
-rw-r--r-- | drivers/video/riva/fbdev.c | 222 |
1 files changed, 159 insertions, 63 deletions
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 3e9308f0f165..d4384ab1df65 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/fb.h> | 41 | #include <linux/fb.h> |
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/pci.h> | 43 | #include <linux/pci.h> |
44 | #include <linux/backlight.h> | ||
44 | #ifdef CONFIG_MTRR | 45 | #ifdef CONFIG_MTRR |
45 | #include <asm/mtrr.h> | 46 | #include <asm/mtrr.h> |
46 | #endif | 47 | #endif |
@@ -272,34 +273,154 @@ static const struct riva_regs reg_template = { | |||
272 | /* | 273 | /* |
273 | * Backlight control | 274 | * Backlight control |
274 | */ | 275 | */ |
275 | #ifdef CONFIG_PMAC_BACKLIGHT | 276 | #ifdef CONFIG_FB_RIVA_BACKLIGHT |
277 | /* We do not have any information about which values are allowed, thus | ||
278 | * we used safe values. | ||
279 | */ | ||
280 | #define MIN_LEVEL 0x158 | ||
281 | #define MAX_LEVEL 0x534 | ||
276 | 282 | ||
277 | static int riva_backlight_levels[] = { | 283 | static struct backlight_properties riva_bl_data; |
278 | 0x158, | 284 | |
279 | 0x192, | 285 | static int riva_bl_get_level_brightness(struct riva_par *par, |
280 | 0x1c6, | 286 | int level) |
281 | 0x200, | 287 | { |
282 | 0x234, | 288 | struct fb_info *info = pci_get_drvdata(par->pdev); |
283 | 0x268, | 289 | int nlevel; |
284 | 0x2a2, | 290 | |
285 | 0x2d6, | 291 | /* Get and convert the value */ |
286 | 0x310, | 292 | mutex_lock(&info->bl_mutex); |
287 | 0x344, | 293 | nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; |
288 | 0x378, | 294 | mutex_unlock(&info->bl_mutex); |
289 | 0x3b2, | 295 | |
290 | 0x3e6, | 296 | if (nlevel < 0) |
291 | 0x41a, | 297 | nlevel = 0; |
292 | 0x454, | 298 | else if (nlevel < MIN_LEVEL) |
293 | 0x534, | 299 | nlevel = MIN_LEVEL; |
294 | }; | 300 | else if (nlevel > MAX_LEVEL) |
301 | nlevel = MAX_LEVEL; | ||
302 | |||
303 | return nlevel; | ||
304 | } | ||
305 | |||
306 | static int riva_bl_update_status(struct backlight_device *bd) | ||
307 | { | ||
308 | struct riva_par *par = class_get_devdata(&bd->class_dev); | ||
309 | U032 tmp_pcrt, tmp_pmc; | ||
310 | int level; | ||
311 | |||
312 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
313 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
314 | level = 0; | ||
315 | else | ||
316 | level = bd->props->brightness; | ||
317 | |||
318 | tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; | ||
319 | tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; | ||
320 | if(level > 0) { | ||
321 | tmp_pcrt |= 0x1; | ||
322 | tmp_pmc |= (1 << 31); /* backlight bit */ | ||
323 | tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */ | ||
324 | } | ||
325 | par->riva.PCRTC0[0x081C/4] = tmp_pcrt; | ||
326 | par->riva.PMC[0x10F0/4] = tmp_pmc; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int riva_bl_get_brightness(struct backlight_device *bd) | ||
332 | { | ||
333 | return bd->props->brightness; | ||
334 | } | ||
295 | 335 | ||
296 | static int riva_set_backlight_enable(int on, int level, void *data); | 336 | static struct backlight_properties riva_bl_data = { |
297 | static int riva_set_backlight_level(int level, void *data); | 337 | .owner = THIS_MODULE, |
298 | static struct backlight_controller riva_backlight_controller = { | 338 | .get_brightness = riva_bl_get_brightness, |
299 | riva_set_backlight_enable, | 339 | .update_status = riva_bl_update_status, |
300 | riva_set_backlight_level | 340 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
301 | }; | 341 | }; |
302 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 342 | |
343 | static void riva_bl_init(struct riva_par *par) | ||
344 | { | ||
345 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
346 | struct backlight_device *bd; | ||
347 | char name[12]; | ||
348 | |||
349 | if (!par->FlatPanel) | ||
350 | return; | ||
351 | |||
352 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
353 | if (!machine_is(powermac) || | ||
354 | !pmac_has_backlight_type("mnca")) | ||
355 | return; | ||
356 | #endif | ||
357 | |||
358 | snprintf(name, sizeof(name), "rivabl%d", info->node); | ||
359 | |||
360 | bd = backlight_device_register(name, par, &riva_bl_data); | ||
361 | if (IS_ERR(bd)) { | ||
362 | info->bl_dev = NULL; | ||
363 | printk("riva: Backlight registration failed\n"); | ||
364 | goto error; | ||
365 | } | ||
366 | |||
367 | mutex_lock(&info->bl_mutex); | ||
368 | info->bl_dev = bd; | ||
369 | fb_bl_default_curve(info, 0, | ||
370 | 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, | ||
371 | 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
372 | mutex_unlock(&info->bl_mutex); | ||
373 | |||
374 | up(&bd->sem); | ||
375 | bd->props->brightness = riva_bl_data.max_brightness; | ||
376 | bd->props->power = FB_BLANK_UNBLANK; | ||
377 | bd->props->update_status(bd); | ||
378 | down(&bd->sem); | ||
379 | |||
380 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
381 | mutex_lock(&pmac_backlight_mutex); | ||
382 | if (!pmac_backlight) | ||
383 | pmac_backlight = bd; | ||
384 | mutex_unlock(&pmac_backlight_mutex); | ||
385 | #endif | ||
386 | |||
387 | printk("riva: Backlight initialized (%s)\n", name); | ||
388 | |||
389 | return; | ||
390 | |||
391 | error: | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | static void riva_bl_exit(struct riva_par *par) | ||
396 | { | ||
397 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
398 | |||
399 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
400 | mutex_lock(&pmac_backlight_mutex); | ||
401 | #endif | ||
402 | |||
403 | mutex_lock(&info->bl_mutex); | ||
404 | if (info->bl_dev) { | ||
405 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
406 | if (pmac_backlight == info->bl_dev) | ||
407 | pmac_backlight = NULL; | ||
408 | #endif | ||
409 | |||
410 | backlight_device_unregister(info->bl_dev); | ||
411 | |||
412 | printk("riva: Backlight unloaded\n"); | ||
413 | } | ||
414 | mutex_unlock(&info->bl_mutex); | ||
415 | |||
416 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
417 | mutex_unlock(&pmac_backlight_mutex); | ||
418 | #endif | ||
419 | } | ||
420 | #else | ||
421 | static inline void riva_bl_init(struct riva_par *par) {} | ||
422 | static inline void riva_bl_exit(struct riva_par *par) {} | ||
423 | #endif /* CONFIG_FB_RIVA_BACKLIGHT */ | ||
303 | 424 | ||
304 | /* ------------------------------------------------------------------------- * | 425 | /* ------------------------------------------------------------------------- * |
305 | * | 426 | * |
@@ -973,36 +1094,6 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) | |||
973 | 1094 | ||
974 | /* ------------------------------------------------------------------------- * | 1095 | /* ------------------------------------------------------------------------- * |
975 | * | 1096 | * |
976 | * Backlight operations | ||
977 | * | ||
978 | * ------------------------------------------------------------------------- */ | ||
979 | |||
980 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
981 | static int riva_set_backlight_enable(int on, int level, void *data) | ||
982 | { | ||
983 | struct riva_par *par = data; | ||
984 | U032 tmp_pcrt, tmp_pmc; | ||
985 | |||
986 | tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; | ||
987 | tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; | ||
988 | if(on && (level > BACKLIGHT_OFF)) { | ||
989 | tmp_pcrt |= 0x1; | ||
990 | tmp_pmc |= (1 << 31); // backlight bit | ||
991 | tmp_pmc |= riva_backlight_levels[level-1] << 16; // level | ||
992 | } | ||
993 | par->riva.PCRTC0[0x081C/4] = tmp_pcrt; | ||
994 | par->riva.PMC[0x10F0/4] = tmp_pmc; | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int riva_set_backlight_level(int level, void *data) | ||
999 | { | ||
1000 | return riva_set_backlight_enable(1, level, data); | ||
1001 | } | ||
1002 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
1003 | |||
1004 | /* ------------------------------------------------------------------------- * | ||
1005 | * | ||
1006 | * framebuffer operations | 1097 | * framebuffer operations |
1007 | * | 1098 | * |
1008 | * ------------------------------------------------------------------------- */ | 1099 | * ------------------------------------------------------------------------- */ |
@@ -1247,10 +1338,15 @@ static int rivafb_blank(int blank, struct fb_info *info) | |||
1247 | SEQout(par, 0x01, tmp); | 1338 | SEQout(par, 0x01, tmp); |
1248 | CRTCout(par, 0x1a, vesa); | 1339 | CRTCout(par, 0x1a, vesa); |
1249 | 1340 | ||
1250 | #ifdef CONFIG_PMAC_BACKLIGHT | 1341 | #ifdef CONFIG_FB_RIVA_BACKLIGHT |
1251 | if ( par->FlatPanel && machine_is(powermac)) { | 1342 | mutex_lock(&info->bl_mutex); |
1252 | set_backlight_enable(!blank); | 1343 | if (info->bl_dev) { |
1344 | down(&info->bl_dev->sem); | ||
1345 | info->bl_dev->props->power = blank; | ||
1346 | info->bl_dev->props->update_status(info->bl_dev); | ||
1347 | up(&info->bl_dev->sem); | ||
1253 | } | 1348 | } |
1349 | mutex_unlock(&info->bl_mutex); | ||
1254 | #endif | 1350 | #endif |
1255 | 1351 | ||
1256 | NVTRACE_LEAVE(); | 1352 | NVTRACE_LEAVE(); |
@@ -2037,11 +2133,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, | |||
2037 | RIVAFB_VERSION, | 2133 | RIVAFB_VERSION, |
2038 | info->fix.smem_len / (1024 * 1024), | 2134 | info->fix.smem_len / (1024 * 1024), |
2039 | info->fix.smem_start); | 2135 | info->fix.smem_start); |
2040 | #ifdef CONFIG_PMAC_BACKLIGHT | 2136 | |
2041 | if (default_par->FlatPanel && machine_is(powermac)) | 2137 | riva_bl_init(info->par); |
2042 | register_backlight_controller(&riva_backlight_controller, | 2138 | |
2043 | default_par, "mnca"); | ||
2044 | #endif | ||
2045 | NVTRACE_LEAVE(); | 2139 | NVTRACE_LEAVE(); |
2046 | return 0; | 2140 | return 0; |
2047 | 2141 | ||
@@ -2074,6 +2168,8 @@ static void __exit rivafb_remove(struct pci_dev *pd) | |||
2074 | 2168 | ||
2075 | NVTRACE_ENTER(); | 2169 | NVTRACE_ENTER(); |
2076 | 2170 | ||
2171 | riva_bl_exit(par); | ||
2172 | |||
2077 | #ifdef CONFIG_FB_RIVA_I2C | 2173 | #ifdef CONFIG_FB_RIVA_I2C |
2078 | riva_delete_i2c_busses(par); | 2174 | riva_delete_i2c_busses(par); |
2079 | kfree(par->EDID); | 2175 | kfree(par->EDID); |