aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/riva
diff options
context:
space:
mode:
authorMichael Hanselmann <linux-kernel@hansmi.ch>2006-06-25 08:47:08 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:00:59 -0400
commit5474c120aafe78ca54bf272f7a01107c42da2b21 (patch)
treec1b002a27703ce92c816bfb9844752186e33d403 /drivers/video/riva
parent17660bdd5c1f1a165273c1a59cb5b87670a81cc4 (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')
-rw-r--r--drivers/video/riva/fbdev.c222
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
277static int riva_backlight_levels[] = { 283static struct backlight_properties riva_bl_data;
278 0x158, 284
279 0x192, 285static 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
306static 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
331static int riva_bl_get_brightness(struct backlight_device *bd)
332{
333 return bd->props->brightness;
334}
295 335
296static int riva_set_backlight_enable(int on, int level, void *data); 336static struct backlight_properties riva_bl_data = {
297static int riva_set_backlight_level(int level, void *data); 337 .owner = THIS_MODULE,
298static 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
343static 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
391error:
392 return;
393}
394
395static 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
421static inline void riva_bl_init(struct riva_par *par) {}
422static 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
981static 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
998static 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);