aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
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/macintosh
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/macintosh')
-rw-r--r--drivers/macintosh/Kconfig19
-rw-r--r--drivers/macintosh/Makefile1
-rw-r--r--drivers/macintosh/adbhid.c28
-rw-r--r--drivers/macintosh/via-pmu-backlight.c150
-rw-r--r--drivers/macintosh/via-pmu.c120
5 files changed, 199 insertions, 119 deletions
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index ccf5df44cde4..37cd6ee4586b 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -99,17 +99,22 @@ config PMAC_MEDIABAY
99 devices are not fully supported in the bay as I never had one to 99 devices are not fully supported in the bay as I never had one to
100 try with 100 try with
101 101
102# made a separate option since backlight may end up beeing used
103# on non-powerbook machines (but only on PMU based ones AFAIK)
104config PMAC_BACKLIGHT 102config PMAC_BACKLIGHT
105 bool "Backlight control for LCD screens" 103 bool "Backlight control for LCD screens"
106 depends on ADB_PMU && (BROKEN || !PPC64) 104 depends on ADB_PMU && (BROKEN || !PPC64)
107 help 105 help
108 Say Y here to build in code to manage the LCD backlight on a 106 Say Y here to enable Macintosh specific extensions of the generic
109 Macintosh PowerBook. With this code, the backlight will be turned 107 backlight code. With this enabled, the brightness keys on older
110 on and off appropriately on power-management and lid-open/lid-closed 108 PowerBooks will be enabled so you can change the screen brightness.
111 events; also, the PowerBook button device will be enabled so you can 109 Newer models should use an userspace daemon like pbbuttonsd.
112 change the screen brightness. 110
111config PMAC_BACKLIGHT_LEGACY
112 bool "Provide legacy ioctl's on /dev/pmu for the backlight"
113 depends on PMAC_BACKLIGHT && (BROKEN || !PPC64)
114 help
115 Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for
116 programs which use this old interface. New and updated programs
117 should use the backlight classes in sysfs.
113 118
114config ADB_MACIO 119config ADB_MACIO
115 bool "Include MacIO (CHRP) ADB driver" 120 bool "Include MacIO (CHRP) ADB driver"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6081acdea404..8972e53d2dcb 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o
12obj-$(CONFIG_ANSLCD) += ans-lcd.o 12obj-$(CONFIG_ANSLCD) += ans-lcd.o
13 13
14obj-$(CONFIG_ADB_PMU) += via-pmu.o 14obj-$(CONFIG_ADB_PMU) += via-pmu.o
15obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o
15obj-$(CONFIG_ADB_CUDA) += via-cuda.o 16obj-$(CONFIG_ADB_CUDA) += via-cuda.o
16obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o 17obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
17obj-$(CONFIG_PMAC_SMU) += smu.o 18obj-$(CONFIG_PMAC_SMU) += smu.o
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 394334ec5765..c26e1236b275 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -503,9 +503,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
503 case 0x1f: /* Powerbook button device */ 503 case 0x1f: /* Powerbook button device */
504 { 504 {
505 int down = (data[1] == (data[1] & 0xf)); 505 int down = (data[1] == (data[1] & 0xf));
506#ifdef CONFIG_PMAC_BACKLIGHT 506
507 int backlight = get_backlight_level();
508#endif
509 /* 507 /*
510 * XXX: Where is the contrast control for the passive? 508 * XXX: Where is the contrast control for the passive?
511 * -- Cort 509 * -- Cort
@@ -530,29 +528,17 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
530 528
531 case 0xa: /* brightness decrease */ 529 case 0xa: /* brightness decrease */
532#ifdef CONFIG_PMAC_BACKLIGHT 530#ifdef CONFIG_PMAC_BACKLIGHT
533 if (!disable_kernel_backlight) { 531 if (!disable_kernel_backlight && down)
534 if (down && backlight >= 0) { 532 pmac_backlight_key_down();
535 if (backlight > BACKLIGHT_OFF) 533#endif
536 set_backlight_level(backlight-1);
537 else
538 set_backlight_level(BACKLIGHT_OFF);
539 }
540 }
541#endif /* CONFIG_PMAC_BACKLIGHT */
542 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); 534 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
543 break; 535 break;
544 536
545 case 0x9: /* brightness increase */ 537 case 0x9: /* brightness increase */
546#ifdef CONFIG_PMAC_BACKLIGHT 538#ifdef CONFIG_PMAC_BACKLIGHT
547 if (!disable_kernel_backlight) { 539 if (!disable_kernel_backlight && down)
548 if (down && backlight >= 0) { 540 pmac_backlight_key_up();
549 if (backlight < BACKLIGHT_MAX) 541#endif
550 set_backlight_level(backlight+1);
551 else
552 set_backlight_level(BACKLIGHT_MAX);
553 }
554 }
555#endif /* CONFIG_PMAC_BACKLIGHT */
556 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); 542 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
557 break; 543 break;
558 544
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
new file mode 100644
index 000000000000..b42d05f2aaff
--- /dev/null
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -0,0 +1,150 @@
1/*
2 * Backlight code for via-pmu
3 *
4 * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
5 * Copyright (C) 2001-2002 Benjamin Herrenschmidt
6 * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
7 *
8 */
9
10#include <asm/ptrace.h>
11#include <linux/adb.h>
12#include <linux/pmu.h>
13#include <asm/backlight.h>
14#include <asm/prom.h>
15
16#define MAX_PMU_LEVEL 0xFF
17
18static struct device_node *vias;
19static struct backlight_properties pmu_backlight_data;
20
21static int pmu_backlight_get_level_brightness(struct fb_info *info,
22 int level)
23{
24 int pmulevel;
25
26 /* Get and convert the value */
27 mutex_lock(&info->bl_mutex);
28 pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
29 mutex_unlock(&info->bl_mutex);
30
31 if (pmulevel < 0)
32 pmulevel = 0;
33 else if (pmulevel > MAX_PMU_LEVEL)
34 pmulevel = MAX_PMU_LEVEL;
35
36 return pmulevel;
37}
38
39static int pmu_backlight_update_status(struct backlight_device *bd)
40{
41 struct fb_info *info = class_get_devdata(&bd->class_dev);
42 struct adb_request req;
43 int pmulevel, level = bd->props->brightness;
44
45 if (vias == NULL)
46 return -ENODEV;
47
48 if (bd->props->power != FB_BLANK_UNBLANK ||
49 bd->props->fb_blank != FB_BLANK_UNBLANK)
50 level = 0;
51
52 pmulevel = pmu_backlight_get_level_brightness(info, level);
53
54 pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
55 pmu_wait_complete(&req);
56
57 pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
58 PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
59 pmu_wait_complete(&req);
60
61 return 0;
62}
63
64static int pmu_backlight_get_brightness(struct backlight_device *bd)
65{
66 return bd->props->brightness;
67}
68
69static struct backlight_properties pmu_backlight_data = {
70 .owner = THIS_MODULE,
71 .get_brightness = pmu_backlight_get_brightness,
72 .update_status = pmu_backlight_update_status,
73 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
74};
75
76void __init pmu_backlight_init(struct device_node *in_vias)
77{
78 struct backlight_device *bd;
79 struct fb_info *info;
80 char name[10];
81 int level, autosave;
82
83 vias = in_vias;
84
85 /* Special case for the old PowerBook since I can't test on it */
86 autosave =
87 machine_is_compatible("AAPL,3400/2400") ||
88 machine_is_compatible("AAPL,3500");
89
90 if (!autosave &&
91 !pmac_has_backlight_type("pmu") &&
92 !machine_is_compatible("AAPL,PowerBook1998") &&
93 !machine_is_compatible("PowerBook1,1"))
94 return;
95
96 /* Actually, this is a hack, but I don't know of a better way
97 * to get the first framebuffer device.
98 */
99 info = registered_fb[0];
100 if (!info) {
101 printk("pmubl: No framebuffer found\n");
102 goto error;
103 }
104
105 snprintf(name, sizeof(name), "pmubl%d", info->node);
106
107 bd = backlight_device_register(name, info, &pmu_backlight_data);
108 if (IS_ERR(bd)) {
109 printk("pmubl: Backlight registration failed\n");
110 goto error;
111 }
112
113 mutex_lock(&info->bl_mutex);
114 info->bl_dev = bd;
115 fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
116 mutex_unlock(&info->bl_mutex);
117
118 level = pmu_backlight_data.max_brightness;
119
120 if (autosave) {
121 /* read autosaved value if available */
122 struct adb_request req;
123 pmu_request(&req, NULL, 2, 0xd9, 0);
124 pmu_wait_complete(&req);
125
126 mutex_lock(&info->bl_mutex);
127 level = pmac_backlight_curve_lookup(info,
128 (req.reply[0] >> 4) *
129 pmu_backlight_data.max_brightness / 15);
130 mutex_unlock(&info->bl_mutex);
131 }
132
133 up(&bd->sem);
134 bd->props->brightness = level;
135 bd->props->power = FB_BLANK_UNBLANK;
136 bd->props->update_status(bd);
137 down(&bd->sem);
138
139 mutex_lock(&pmac_backlight_mutex);
140 if (!pmac_backlight)
141 pmac_backlight = bd;
142 mutex_unlock(&pmac_backlight_mutex);
143
144 printk("pmubl: Backlight initialized (%s)\n", name);
145
146 return;
147
148error:
149 return;
150}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index c63d4e7984be..2a355ae59562 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -144,7 +144,6 @@ static int data_index;
144static int data_len; 144static int data_len;
145static volatile int adb_int_pending; 145static volatile int adb_int_pending;
146static volatile int disable_poll; 146static volatile int disable_poll;
147static struct adb_request bright_req_1, bright_req_2;
148static struct device_node *vias; 147static struct device_node *vias;
149static int pmu_kind = PMU_UNKNOWN; 148static int pmu_kind = PMU_UNKNOWN;
150static int pmu_fully_inited = 0; 149static int pmu_fully_inited = 0;
@@ -161,7 +160,7 @@ static int drop_interrupts;
161#if defined(CONFIG_PM) && defined(CONFIG_PPC32) 160#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
162static int option_lid_wakeup = 1; 161static int option_lid_wakeup = 1;
163#endif /* CONFIG_PM && CONFIG_PPC32 */ 162#endif /* CONFIG_PM && CONFIG_PPC32 */
164#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) 163#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
165static int sleep_in_progress; 164static int sleep_in_progress;
166#endif 165#endif
167static unsigned long async_req_locks; 166static unsigned long async_req_locks;
@@ -208,10 +207,6 @@ static int proc_get_info(char *page, char **start, off_t off,
208 int count, int *eof, void *data); 207 int count, int *eof, void *data);
209static int proc_get_irqstats(char *page, char **start, off_t off, 208static int proc_get_irqstats(char *page, char **start, off_t off,
210 int count, int *eof, void *data); 209 int count, int *eof, void *data);
211#ifdef CONFIG_PMAC_BACKLIGHT
212static int pmu_set_backlight_level(int level, void* data);
213static int pmu_set_backlight_enable(int on, int level, void* data);
214#endif /* CONFIG_PMAC_BACKLIGHT */
215static void pmu_pass_intr(unsigned char *data, int len); 210static void pmu_pass_intr(unsigned char *data, int len);
216static int proc_get_batt(char *page, char **start, off_t off, 211static int proc_get_batt(char *page, char **start, off_t off,
217 int count, int *eof, void *data); 212 int count, int *eof, void *data);
@@ -292,13 +287,6 @@ static char *pbook_type[] = {
292 "Core99" 287 "Core99"
293}; 288};
294 289
295#ifdef CONFIG_PMAC_BACKLIGHT
296static struct backlight_controller pmu_backlight_controller = {
297 pmu_set_backlight_enable,
298 pmu_set_backlight_level
299};
300#endif /* CONFIG_PMAC_BACKLIGHT */
301
302int __init find_via_pmu(void) 290int __init find_via_pmu(void)
303{ 291{
304 u64 taddr; 292 u64 taddr;
@@ -417,8 +405,6 @@ static int __init via_pmu_start(void)
417 if (vias == NULL) 405 if (vias == NULL)
418 return -ENODEV; 406 return -ENODEV;
419 407
420 bright_req_1.complete = 1;
421 bright_req_2.complete = 1;
422 batt_req.complete = 1; 408 batt_req.complete = 1;
423 409
424#ifndef CONFIG_PPC_MERGE 410#ifndef CONFIG_PPC_MERGE
@@ -483,9 +469,9 @@ static int __init via_pmu_dev_init(void)
483 return -ENODEV; 469 return -ENODEV;
484 470
485#ifdef CONFIG_PMAC_BACKLIGHT 471#ifdef CONFIG_PMAC_BACKLIGHT
486 /* Enable backlight */ 472 /* Initialize backlight */
487 register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); 473 pmu_backlight_init(vias);
488#endif /* CONFIG_PMAC_BACKLIGHT */ 474#endif
489 475
490#ifdef CONFIG_PPC32 476#ifdef CONFIG_PPC32
491 if (machine_is_compatible("AAPL,3400/2400") || 477 if (machine_is_compatible("AAPL,3400/2400") ||
@@ -1424,7 +1410,7 @@ next:
1424#ifdef CONFIG_INPUT_ADBHID 1410#ifdef CONFIG_INPUT_ADBHID
1425 if (!disable_kernel_backlight) 1411 if (!disable_kernel_backlight)
1426#endif /* CONFIG_INPUT_ADBHID */ 1412#endif /* CONFIG_INPUT_ADBHID */
1427 set_backlight_level(data[1] >> 4); 1413 pmac_backlight_set_legacy_brightness(data[1] >> 4);
1428#endif /* CONFIG_PMAC_BACKLIGHT */ 1414#endif /* CONFIG_PMAC_BACKLIGHT */
1429 } 1415 }
1430 /* Tick interrupt */ 1416 /* Tick interrupt */
@@ -1674,61 +1660,6 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
1674 return IRQ_NONE; 1660 return IRQ_NONE;
1675} 1661}
1676 1662
1677#ifdef CONFIG_PMAC_BACKLIGHT
1678static int backlight_to_bright[] = {
1679 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
1680 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
1681};
1682
1683static int
1684pmu_set_backlight_enable(int on, int level, void* data)
1685{
1686 struct adb_request req;
1687
1688 if (vias == NULL)
1689 return -ENODEV;
1690
1691 if (on) {
1692 pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
1693 backlight_to_bright[level]);
1694 pmu_wait_complete(&req);
1695 }
1696 pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
1697 PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
1698 pmu_wait_complete(&req);
1699
1700 return 0;
1701}
1702
1703static void
1704pmu_bright_complete(struct adb_request *req)
1705{
1706 if (req == &bright_req_1)
1707 clear_bit(1, &async_req_locks);
1708 if (req == &bright_req_2)
1709 clear_bit(2, &async_req_locks);
1710}
1711
1712static int
1713pmu_set_backlight_level(int level, void* data)
1714{
1715 if (vias == NULL)
1716 return -ENODEV;
1717
1718 if (test_and_set_bit(1, &async_req_locks))
1719 return -EAGAIN;
1720 pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT,
1721 backlight_to_bright[level]);
1722 if (test_and_set_bit(2, &async_req_locks))
1723 return -EAGAIN;
1724 pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL,
1725 PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ?
1726 PMU_POW_ON : PMU_POW_OFF));
1727
1728 return 0;
1729}
1730#endif /* CONFIG_PMAC_BACKLIGHT */
1731
1732void 1663void
1733pmu_enable_irled(int on) 1664pmu_enable_irled(int on)
1734{ 1665{
@@ -2145,9 +2076,8 @@ pmac_suspend_devices(void)
2145 return -EBUSY; 2076 return -EBUSY;
2146 } 2077 }
2147 2078
2148 /* Wait for completion of async backlight requests */ 2079 /* Wait for completion of async requests */
2149 while (!bright_req_1.complete || !bright_req_2.complete || 2080 while (!batt_req.complete)
2150 !batt_req.complete)
2151 pmu_poll(); 2081 pmu_poll();
2152 2082
2153 /* Giveup the lazy FPU & vec so we don't have to back them 2083 /* Giveup the lazy FPU & vec so we don't have to back them
@@ -2678,26 +2608,34 @@ pmu_ioctl(struct inode * inode, struct file *filp,
2678 return put_user(1, argp); 2608 return put_user(1, argp);
2679#endif /* CONFIG_PM && CONFIG_PPC32 */ 2609#endif /* CONFIG_PM && CONFIG_PPC32 */
2680 2610
2681#ifdef CONFIG_PMAC_BACKLIGHT 2611#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
2682 /* Backlight should have its own device or go via 2612 /* Compatibility ioctl's for backlight */
2683 * the fbdev
2684 */
2685 case PMU_IOC_GET_BACKLIGHT: 2613 case PMU_IOC_GET_BACKLIGHT:
2614 {
2615 int brightness;
2616
2686 if (sleep_in_progress) 2617 if (sleep_in_progress)
2687 return -EBUSY; 2618 return -EBUSY;
2688 error = get_backlight_level(); 2619
2689 if (error < 0) 2620 brightness = pmac_backlight_get_legacy_brightness();
2690 return error; 2621 if (brightness < 0)
2691 return put_user(error, argp); 2622 return brightness;
2623 else
2624 return put_user(brightness, argp);
2625
2626 }
2692 case PMU_IOC_SET_BACKLIGHT: 2627 case PMU_IOC_SET_BACKLIGHT:
2693 { 2628 {
2694 __u32 value; 2629 int brightness;
2630
2695 if (sleep_in_progress) 2631 if (sleep_in_progress)
2696 return -EBUSY; 2632 return -EBUSY;
2697 error = get_user(value, argp); 2633
2698 if (!error) 2634 error = get_user(brightness, argp);
2699 error = set_backlight_level(value); 2635 if (error)
2700 break; 2636 return error;
2637
2638 return pmac_backlight_set_legacy_brightness(brightness);
2701 } 2639 }
2702#ifdef CONFIG_INPUT_ADBHID 2640#ifdef CONFIG_INPUT_ADBHID
2703 case PMU_IOC_GRAB_BACKLIGHT: { 2641 case PMU_IOC_GRAB_BACKLIGHT: {
@@ -2713,7 +2651,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
2713 return 0; 2651 return 0;
2714 } 2652 }
2715#endif /* CONFIG_INPUT_ADBHID */ 2653#endif /* CONFIG_INPUT_ADBHID */
2716#endif /* CONFIG_PMAC_BACKLIGHT */ 2654#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
2717 case PMU_IOC_GET_MODEL: 2655 case PMU_IOC_GET_MODEL:
2718 return put_user(pmu_kind, argp); 2656 return put_user(pmu_kind, argp);
2719 case PMU_IOC_HAS_ADB: 2657 case PMU_IOC_HAS_ADB: