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