1 /* 2 * Fujitsu Lifebook Application Panel button drive 3 * 4 * Copyright (C) 2007 Stephen Hemminger <shemminger@linux-foundation.org> 5 * Copyright (C) 2001-2003 Jochen Eisinger <jochen@penguin-breeder.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * Many Fujitsu Lifebook laptops have a small panel of buttons that are 12 * accessible via the i2c/smbus interface. This driver polls those 13 * buttons and generates input events. 14 * 15 * For more details see: 16 * http://apanel.sourceforge.net/tech.php 17 */ 18 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/ioport.h> 22 #include <linux/io.h> 23 #include <linux/module.h> 24 #include <linux/input-polldev.h> 25 #include <linux/i2c.h> 26 #include <linux/workqueue.h> 27 #include <linux/leds.h> 28 29 #define APANEL_NAME "Fujitsu Application Panel" 30 #define APANEL_VERSION "1.3.1" 31 #define APANEL "apanel" 32 33 /* How often we poll keys - msecs */ 34 #define POLL_INTERVAL_DEFAULT 1000 35 36 /* Magic constants in BIOS that tell about buttons */ 37 enum apanel_devid { 38 APANEL_DEV_NONE = 0, 39 APANEL_DEV_APPBTN = 1, 40 APANEL_DEV_CDBTN = 2, 41 APANEL_DEV_LCD = 3, 42 APANEL_DEV_LED = 4, 43 44 APANEL_DEV_MAX, 45 }; 46 47 enum apanel_chip { 48 CHIP_NONE = 0, 49 CHIP_OZ992C = 1, 50 CHIP_OZ163T = 2, 51 CHIP_OZ711M3 = 4, 52 }; 53 54 /* Result of BIOS snooping/probing -- what features are supported */ 55 static enum apanel_chip device_chip[APANEL_DEV_MAX]; 56 57 #define MAX_PANEL_KEYS 12 58 59 struct apanel { 60 struct input_polled_dev *ipdev; 61 struct i2c_client client; 62 unsigned short keymap[MAX_PANEL_KEYS]; 63 u16 nkeys; 64 u16 led_bits; 65 struct work_struct led_work; 66 struct led_classdev mail_led; 67 }; 68 69 70 static int apanel_probe(struct i2c_adapter *, int, int); 71 72 /* for now, we only support one address */ 73 static unsigned short normal_i2c[] = {0, I2C_CLIENT_END}; 74 static unsigned short ignore = I2C_CLIENT_END; 75 static struct i2c_client_address_data addr_data = { 76 .normal_i2c = normal_i2c, 77 .probe = &ignore, 78 .ignore = &ignore, 79 }; 80 81 static void report_key(struct input_dev *input, unsigned keycode) 82 { 83 pr_debug(APANEL ": report key %#x\n", keycode); 84 input_report_key(input, keycode, 1); 85 input_sync(input); 86 87 input_report_key(input, keycode, 0); 88 input_sync(input); 89 } 90 91 /* Poll for key changes 92 * 93 * Read Application keys via SMI 94 * A (0x4), B (0x8), Internet (0x2), Email (0x1). 95 * 96 * CD keys: 97 * Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800) 98 */ 99 static void apanel_poll(struct input_polled_dev *ipdev) 100 { 101 struct apanel *ap = ipdev->private; 102 struct input_dev *idev = ipdev->input; 103 u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; 104 s32 data; 105 int i; 106 107 data = i2c_smbus_read_word_data(&ap->client, cmd); 108 if (data < 0) 109 return; /* ignore errors (due to ACPI??) */ 110 111 /* write back to clear latch */ 112 i2c_smbus_write_word_data(&ap->client, cmd, 0); 113 114 if (!data) 115 return; 116 117 dev_dbg(&idev->dev, APANEL ": data %#x\n", data); 118 for (i = 0; i < idev->keycodemax; i++) 119 if ((1u << i) & data) 120 report_key(idev, ap->keymap[i]); 121 } 122 123 /* Track state changes of LED */ 124 static void led_update(struct work_struct *work) 125 { 126 struct apanel *ap = container_of(work, struct apanel, led_work); 127 128 i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits); 129 } 130 131 static void mail_led_set(struct led_classdev *led, 132 enum led_brightness value) 133 { 134 struct apanel *ap = container_of(led, struct apanel, mail_led); 135 136 if (value != LED_OFF) 137 ap->led_bits |= 0x8000; 138 else 139 ap->led_bits &= ~0x8000; 140 141 schedule_work(&ap->led_work); 142 } 143 144 static int apanel_detach_client(struct i2c_client *client) 145 { 146 struct apanel *ap = i2c_get_clientdata(client); 147 148 if (device_chip[APANEL_DEV_LED] != CHIP_NONE) 149 led_classdev_unregister(&ap->mail_led); 150 151 input_unregister_polled_device(ap->ipdev); 152 i2c_detach_client(&ap->client); 153 input_free_polled_device(ap->ipdev); 154 155 return 0; 156 } 157 158 /* Function is invoked for every i2c adapter. */ 159 static int apanel_attach_adapter(struct i2c_adapter *adap) 160 { 161 dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id); 162 163 /* Our device is connected only to i801 on laptop */ 164 if (adap->id != I2C_HW_SMBUS_I801) 165 return -ENODEV; 166 167 return i2c_probe(adap, &addr_data, apanel_probe); 168 } 169 170 static void apanel_shutdown(struct i2c_client *client) 171 { 172 apanel_detach_client(client); 173 } 174 175 static struct i2c_driver apanel_driver = { 176 .driver = { 177 .name = APANEL, 178 }, 179 .attach_adapter = &apanel_attach_adapter, 180 .detach_client = &apanel_detach_client, 181 .shutdown = &apanel_shutdown, 182 }; 183 184 static struct apanel apanel = { 185 .client = { 186 .driver = &apanel_driver, 187 .name = APANEL, 188 }, 189 .keymap = { 190 [0] = KEY_MAIL, 191 [1] = KEY_WWW, 192 [2] = KEY_PROG2, 193 [3] = KEY_PROG1, 194 195 [8] = KEY_FORWARD, 196 [9] = KEY_REWIND, 197 [10] = KEY_STOPCD, 198 [11] = KEY_PLAYPAUSE, 199 200 }, 201 .mail_led = { 202 .name = "mail:blue", 203 .brightness_set = mail_led_set, 204 }, 205 }; 206 207 /* NB: Only one panel on the i2c. */ 208 static int apanel_probe(struct i2c_adapter *bus, int address, int kind) 209 { 210 struct apanel *ap; 211 struct input_polled_dev *ipdev; 212 struct input_dev *idev; 213 u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; 214 int i, err = -ENOMEM; 215 216 dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n", 217 bus, address, kind); 218 219 ap = &apanel; 220 221 ipdev = input_allocate_polled_device(); 222 if (!ipdev) 223 goto out1; 224 225 ap->ipdev = ipdev; 226 ap->client.adapter = bus; 227 ap->client.addr = address; 228 229 i2c_set_clientdata(&ap->client, ap); 230 231 err = i2c_attach_client(&ap->client); 232 if (err) 233 goto out2; 234 235 err = i2c_smbus_write_word_data(&ap->client, cmd, 0); 236 if (err) { 237 dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n", 238 err); 239 goto out3; 240 } 241 242 ipdev->poll = apanel_poll; 243 ipdev->poll_interval = POLL_INTERVAL_DEFAULT; 244 ipdev->private = ap; 245 246 idev = ipdev->input; 247 idev->name = APANEL_NAME " buttons"; 248 idev->phys = "apanel/input0"; 249 idev->id.bustype = BUS_HOST; 250 idev->dev.parent = &ap->client.dev; 251 252 set_bit(EV_KEY, idev->evbit); 253 254 idev->keycode = ap->keymap; 255 idev->keycodesize = sizeof(ap->keymap[0]); 256 idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; 257 258 for (i = 0; i < idev->keycodemax; i++) 259 if (ap->keymap[i]) 260 set_bit(ap->keymap[i], idev->keybit); 261 262 err = input_register_polled_device(ipdev); 263 if (err) 264 goto out3; 265 266 INIT_WORK(&ap->led_work, led_update); 267 if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { 268 err = led_classdev_register(&ap->client.dev, &ap->mail_led); 269 if (err) 270 goto out4; 271 } 272 273 return 0; 274 out4: 275 input_unregister_polled_device(ipdev); 276 out3: 277 i2c_detach_client(&ap->client); 278 out2: 279 input_free_polled_device(ipdev); 280 out1: 281 return err; 282 } 283 284 /* Scan the system ROM for the signature "FJKEYINF" */ 285 static __init const void __iomem *bios_signature(const void __iomem *bios) 286 { 287 ssize_t offset; 288 const unsigned char signature[] = "FJKEYINF"; 289 290 for (offset = 0; offset < 0x10000; offset += 0x10) { 291 if (check_signature(bios + offset, signature, 292 sizeof(signature)-1)) 293 return bios + offset; 294 } 295 pr_notice(APANEL ": Fujitsu BIOS signature '%s' not found...\n", 296 signature); 297 return NULL; 298 } 299 300 static int __init apanel_init(void) 301 { 302 void __iomem *bios; 303 const void __iomem *p; 304 u8 devno; 305 int found = 0; 306 307 bios = ioremap(0xF0000, 0x10000); /* Can't fail */ 308 309 p = bios_signature(bios); 310 if (!p) { 311 iounmap(bios); 312 return -ENODEV; 313 } 314 315 /* just use the first address */ 316 p += 8; 317 normal_i2c[0] = readb(p+3) >> 1; 318 319 for ( ; (devno = readb(p)) & 0x7f; p += 4) { 320 unsigned char method, slave, chip; 321 322 method = readb(p + 1); 323 chip = readb(p + 2); 324 slave = readb(p + 3) >> 1; 325 326 if (slave != normal_i2c[0]) { 327 pr_notice(APANEL ": only one SMBus slave " 328 "address supported, skiping device...\n"); 329 continue; 330 } 331 332 /* translate alternative device numbers */ 333 switch (devno) { 334 case 6: 335 devno = APANEL_DEV_APPBTN; 336 break; 337 case 7: 338 devno = APANEL_DEV_LED; 339 break; 340 } 341 342 if (devno >= APANEL_DEV_MAX) 343 pr_notice(APANEL ": unknown device %u found\n", devno); 344 else if (device_chip[devno] != CHIP_NONE) 345 pr_warning(APANEL ": duplicate entry for devno %u\n", devno); 346 347 else if (method != 1 && method != 2 && method != 4) { 348 pr_notice(APANEL ": unknown method %u for devno %u\n", 349 method, devno); 350 } else { 351 device_chip[devno] = (enum apanel_chip) chip; 352 ++found; 353 } 354 } 355 iounmap(bios); 356 357 if (found == 0) { 358 pr_info(APANEL ": no input devices reported by BIOS\n"); 359 return -EIO; 360 } 361 362 return i2c_add_driver(&apanel_driver); 363 } 364 module_init(apanel_init); 365 366 static void __exit apanel_cleanup(void) 367 { 368 i2c_del_driver(&apanel_driver); 369 } 370 module_exit(apanel_cleanup); 371 372 MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); 373 MODULE_DESCRIPTION(APANEL_NAME " driver"); 374 MODULE_LICENSE("GPL"); 375 MODULE_VERSION(APANEL_VERSION); 376 377 MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifeBook*:pvr*:rvnFUJITSU:*"); 378 MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifebook*:pvr*:rvnFUJITSU:*"); 379