aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMario Schwalbe <schwalbe@inf.tu-dresden.de>2009-01-10 19:11:34 -0500
committerRichard Purdie <rpurdie@linux.intel.com>2009-04-06 11:06:55 -0400
commitc78a628849675580c7c5e1f07193c632e4b6827f (patch)
treecfeb5bf04e1a33b2ebeacabe9a0854cc8b1e2473 /drivers
parent0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff)
backlight: Add support for MacBook 5, MacBook Air 2, and MacBook Pro 5
This patch adds support for the new Apple models incorporating an Nvidia chipset. Apple still uses the same protocol as on older models, but the registers moved to a different address. To do this, two sets of functions are added for the Intel/Nvidia chipset models and passed by the DMI_MATCH function. The initial code has been contributed by Hu Gang <hugang@soulinfo.com>. The driver is known to work on MacBook Pro 3, MacBook Pro 4 and MacBook Pro 5. Its known to work with limitations on MacBook 5 / MacBook Air 2. Changing brightness within X doesn't work, if using Nvidia's proprietary graphics driver with no known fix at present. Changing brightness on a text console or using the open-source driver does work. MacBook Pro 5 has a known bug where the initial brightness after bootup is the last recently used brightness (in Mac OSX), while the firmware reports maximum. Impossible to fix. [akpm@linux-foundation.org: build fix] [rpurdie@linux.intel.com: Rebased the patch against latest git] Signed-off-by: Mario Schwalbe <schwalbe@inf.tu-dresden.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c162
1 files changed, 126 insertions, 36 deletions
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 65864c500455..ce09b83244ac 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -27,52 +27,142 @@
27 27
28static struct backlight_device *mbp_backlight_device; 28static struct backlight_device *mbp_backlight_device;
29 29
30static struct dmi_system_id __initdata mbp_device_table[] = { 30/* Structure to be passed to the DMI_MATCH function. */
31 { 31struct dmi_match_data {
32 .ident = "3,1", 32 /* I/O resource to allocate. */
33 .matches = { 33 unsigned long iostart;
34 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 34 unsigned long iolen;
35 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), 35 /* Backlight operations structure. */
36 }, 36 struct backlight_ops backlight_ops;
37 },
38 {
39 .ident = "3,2",
40 .matches = {
41 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
42 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
43 },
44 },
45 {
46 .ident = "4,1",
47 .matches = {
48 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
49 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
50 },
51 },
52 { }
53}; 37};
54 38
55static int mbp_send_intensity(struct backlight_device *bd) 39/*
40 * Implementation for MacBooks with Intel chipset.
41 */
42static int intel_chipset_send_intensity(struct backlight_device *bd)
56{ 43{
57 int intensity = bd->props.brightness; 44 int intensity = bd->props.brightness;
58 45
59 outb(0x04 | (intensity << 4), 0xb3); 46 outb(0x04 | (intensity << 4), 0xb3);
60 outb(0xbf, 0xb2); 47 outb(0xbf, 0xb2);
61
62 return 0; 48 return 0;
63} 49}
64 50
65static int mbp_get_intensity(struct backlight_device *bd) 51static int intel_chipset_get_intensity(struct backlight_device *bd)
66{ 52{
67 outb(0x03, 0xb3); 53 outb(0x03, 0xb3);
68 outb(0xbf, 0xb2); 54 outb(0xbf, 0xb2);
69 return inb(0xb3) >> 4; 55 return inb(0xb3) >> 4;
70} 56}
71 57
72static struct backlight_ops mbp_ops = { 58static const struct dmi_match_data intel_chipset_data = {
73 .options = BL_CORE_SUSPENDRESUME, 59 .iostart = 0xb2,
74 .get_brightness = mbp_get_intensity, 60 .iolen = 2,
75 .update_status = mbp_send_intensity, 61 .backlight_ops = {
62 .options = BL_CORE_SUSPENDRESUME,
63 .get_brightness = intel_chipset_get_intensity,
64 .update_status = intel_chipset_send_intensity,
65 }
66};
67
68/*
69 * Implementation for MacBooks with Nvidia chipset.
70 */
71static int nvidia_chipset_send_intensity(struct backlight_device *bd)
72{
73 int intensity = bd->props.brightness;
74
75 outb(0x04 | (intensity << 4), 0x52f);
76 outb(0xbf, 0x52e);
77 return 0;
78}
79
80static int nvidia_chipset_get_intensity(struct backlight_device *bd)
81{
82 outb(0x03, 0x52f);
83 outb(0xbf, 0x52e);
84 return inb(0x52f) >> 4;
85}
86
87static const struct dmi_match_data nvidia_chipset_data = {
88 .iostart = 0x52e,
89 .iolen = 2,
90 .backlight_ops = {
91 .options = BL_CORE_SUSPENDRESUME,
92 .get_brightness = nvidia_chipset_get_intensity,
93 .update_status = nvidia_chipset_send_intensity
94 }
95};
96
97/*
98 * DMI matching.
99 */
100static /* const */ struct dmi_match_data *driver_data;
101
102static int mbp_dmi_match(const struct dmi_system_id *id)
103{
104 driver_data = id->driver_data;
105
106 printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident);
107 return 1;
108}
109
110static const struct dmi_system_id __initdata mbp_device_table[] = {
111 {
112 .callback = mbp_dmi_match,
113 .ident = "MacBookPro 3,1",
114 .matches = {
115 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
116 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
117 },
118 .driver_data = (void *)&intel_chipset_data,
119 },
120 {
121 .callback = mbp_dmi_match,
122 .ident = "MacBookPro 3,2",
123 .matches = {
124 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
125 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
126 },
127 .driver_data = (void *)&intel_chipset_data,
128 },
129 {
130 .callback = mbp_dmi_match,
131 .ident = "MacBookPro 4,1",
132 .matches = {
133 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
134 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
135 },
136 .driver_data = (void *)&intel_chipset_data,
137 },
138 {
139 .callback = mbp_dmi_match,
140 .ident = "MacBook 5,1",
141 .matches = {
142 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
143 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
144 },
145 .driver_data = (void *)&nvidia_chipset_data,
146 },
147 {
148 .callback = mbp_dmi_match,
149 .ident = "MacBookAir 2,1",
150 .matches = {
151 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
152 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
153 },
154 .driver_data = (void *)&nvidia_chipset_data,
155 },
156 {
157 .callback = mbp_dmi_match,
158 .ident = "MacBookPro 5,1",
159 .matches = {
160 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
161 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
162 },
163 .driver_data = (void *)&nvidia_chipset_data,
164 },
165 { }
76}; 166};
77 167
78static int __init mbp_init(void) 168static int __init mbp_init(void)
@@ -80,20 +170,20 @@ static int __init mbp_init(void)
80 if (!dmi_check_system(mbp_device_table)) 170 if (!dmi_check_system(mbp_device_table))
81 return -ENODEV; 171 return -ENODEV;
82 172
83 if (!request_region(0xb2, 2, "Macbook Pro backlight")) 173 if (!request_region(driver_data->iostart, driver_data->iolen,
174 "Macbook Pro backlight"))
84 return -ENXIO; 175 return -ENXIO;
85 176
86 mbp_backlight_device = backlight_device_register("mbp_backlight", 177 mbp_backlight_device = backlight_device_register("mbp_backlight",
87 NULL, NULL, 178 NULL, NULL, &driver_data->backlight_ops);
88 &mbp_ops);
89 if (IS_ERR(mbp_backlight_device)) { 179 if (IS_ERR(mbp_backlight_device)) {
90 release_region(0xb2, 2); 180 release_region(driver_data->iostart, driver_data->iolen);
91 return PTR_ERR(mbp_backlight_device); 181 return PTR_ERR(mbp_backlight_device);
92 } 182 }
93 183
94 mbp_backlight_device->props.max_brightness = 15; 184 mbp_backlight_device->props.max_brightness = 15;
95 mbp_backlight_device->props.brightness = 185 mbp_backlight_device->props.brightness =
96 mbp_get_intensity(mbp_backlight_device); 186 driver_data->backlight_ops.get_brightness(mbp_backlight_device);
97 backlight_update_status(mbp_backlight_device); 187 backlight_update_status(mbp_backlight_device);
98 188
99 return 0; 189 return 0;
@@ -103,7 +193,7 @@ static void __exit mbp_exit(void)
103{ 193{
104 backlight_device_unregister(mbp_backlight_device); 194 backlight_device_unregister(mbp_backlight_device);
105 195
106 release_region(0xb2, 2); 196 release_region(driver_data->iostart, driver_data->iolen);
107} 197}
108 198
109module_init(mbp_init); 199module_init(mbp_init);