1 /* 2 * ACPI Sony Notebook Control Driver (SNC and SPIC) 3 * 4 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> 5 * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> 6 * 7 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c 8 * which are copyrighted by their respective authors. 9 * 10 * The SNY6001 driver part is based on the sonypi driver which includes 11 * material from: 12 * 13 * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net> 14 * 15 * Copyright (C) 2005 Narayanan R S <nars@kadamba.org> 16 * 17 * Copyright (C) 2001-2002 Alcôve <www.alcove.com> 18 * 19 * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au> 20 * 21 * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp> 22 * 23 * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp> 24 * 25 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com> 26 * 27 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras. 28 * 29 * This program is free software; you can redistribute it and/or modify 30 * it under the terms of the GNU General Public License as published by 31 * the Free Software Foundation; either version 2 of the License, or 32 * (at your option) any later version. 33 * 34 * This program is distributed in the hope that it will be useful, 35 * but WITHOUT ANY WARRANTY; without even the implied warranty of 36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37 * GNU General Public License for more details. 38 * 39 * You should have received a copy of the GNU General Public License 40 * along with this program; if not, write to the Free Software 41 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 42 * 43 */ 44 45 #include <linux/kernel.h> 46 #include <linux/module.h> 47 #include <linux/moduleparam.h> 48 #include <linux/init.h> 49 #include <linux/smp_lock.h> 50 #include <linux/types.h> 51 #include <linux/backlight.h> 52 #include <linux/platform_device.h> 53 #include <linux/err.h> 54 #include <linux/dmi.h> 55 #include <linux/pci.h> 56 #include <linux/interrupt.h> 57 #include <linux/delay.h> 58 #include <linux/input.h> 59 #include <linux/kfifo.h> 60 #include <linux/workqueue.h> 61 #include <linux/acpi.h> 62 #include <acpi/acpi_drivers.h> 63 #include <acpi/acpi_bus.h> 64 #include <asm/uaccess.h> 65 #include <linux/sonypi.h> 66 #include <linux/sony-laptop.h> 67 #ifdef CONFIG_SONYPI_COMPAT 68 #include <linux/poll.h> 69 #include <linux/miscdevice.h> 70 #endif 71 72 #define DRV_PFX "sony-laptop: " 73 #define dprintk(msg...) do { \ 74 if (debug) printk(KERN_WARNING DRV_PFX msg); \ 75 } while (0) 76 77 #define SONY_LAPTOP_DRIVER_VERSION "0.6" 78 79 #define SONY_NC_CLASS "sony-nc" 80 #define SONY_NC_HID "SNY5001" 81 #define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver" 82 83 #define SONY_PIC_CLASS "sony-pic" 84 #define SONY_PIC_HID "SNY6001" 85 #define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver" 86 87 MODULE_AUTHOR("Stelian Pop, Mattia Dongili"); 88 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)"); 89 MODULE_LICENSE("GPL"); 90 MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION); 91 92 static int debug; 93 module_param(debug, int, 0); 94 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " 95 "the development of this driver"); 96 97 static int no_spic; /* = 0 */ 98 module_param(no_spic, int, 0444); 99 MODULE_PARM_DESC(no_spic, 100 "set this if you don't want to enable the SPIC device"); 101 102 static int compat; /* = 0 */ 103 module_param(compat, int, 0444); 104 MODULE_PARM_DESC(compat, 105 "set this if you want to enable backward compatibility mode"); 106 107 static unsigned long mask = 0xffffffff; 108 module_param(mask, ulong, 0644); 109 MODULE_PARM_DESC(mask, 110 "set this to the mask of event you want to enable (see doc)"); 111 112 static int camera; /* = 0 */ 113 module_param(camera, int, 0444); 114 MODULE_PARM_DESC(camera, 115 "set this to 1 to enable Motion Eye camera controls " 116 "(only use it if you have a C1VE or C1VN model)"); 117 118 #ifdef CONFIG_SONYPI_COMPAT 119 static int minor = -1; 120 module_param(minor, int, 0); 121 MODULE_PARM_DESC(minor, 122 "minor number of the misc device for the SPIC compatibility code, " 123 "default is -1 (automatic)"); 124 #endif 125 126 /*********** Input Devices ***********/ 127 128 #define SONY_LAPTOP_BUF_SIZE 128 129 struct sony_laptop_input_s { 130 atomic_t users; 131 struct input_dev *jog_dev; 132 struct input_dev *key_dev; 133 struct kfifo *fifo; 134 spinlock_t fifo_lock; 135 struct workqueue_struct *wq; 136 }; 137 static struct sony_laptop_input_s sony_laptop_input = { 138 .users = ATOMIC_INIT(0), 139 }; 140 141 struct sony_laptop_keypress { 142 struct input_dev *dev; 143 int key; 144 }; 145 146 /* Correspondance table between sonypi events 147 * and input layer indexes in the keymap 148 */ 149 static int sony_laptop_input_index[] = { 150 -1, /* 0 no event */ 151 -1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */ 152 -1, /* 2 SONYPI_EVENT_JOGDIAL_UP */ 153 -1, /* 3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ 154 -1, /* 4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */ 155 -1, /* 5 SONYPI_EVENT_JOGDIAL_PRESSED */ 156 -1, /* 6 SONYPI_EVENT_JOGDIAL_RELEASED */ 157 0, /* 7 SONYPI_EVENT_CAPTURE_PRESSED */ 158 1, /* 8 SONYPI_EVENT_CAPTURE_RELEASED */ 159 2, /* 9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 160 3, /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 161 4, /* 11 SONYPI_EVENT_FNKEY_ESC */ 162 5, /* 12 SONYPI_EVENT_FNKEY_F1 */ 163 6, /* 13 SONYPI_EVENT_FNKEY_F2 */ 164 7, /* 14 SONYPI_EVENT_FNKEY_F3 */ 165 8, /* 15 SONYPI_EVENT_FNKEY_F4 */ 166 9, /* 16 SONYPI_EVENT_FNKEY_F5 */ 167 10, /* 17 SONYPI_EVENT_FNKEY_F6 */ 168 11, /* 18 SONYPI_EVENT_FNKEY_F7 */ 169 12, /* 19 SONYPI_EVENT_FNKEY_F8 */ 170 13, /* 20 SONYPI_EVENT_FNKEY_F9 */ 171 14, /* 21 SONYPI_EVENT_FNKEY_F10 */ 172 15, /* 22 SONYPI_EVENT_FNKEY_F11 */ 173 16, /* 23 SONYPI_EVENT_FNKEY_F12 */ 174 17, /* 24 SONYPI_EVENT_FNKEY_1 */ 175 18, /* 25 SONYPI_EVENT_FNKEY_2 */ 176 19, /* 26 SONYPI_EVENT_FNKEY_D */ 177 20, /* 27 SONYPI_EVENT_FNKEY_E */ 178 21, /* 28 SONYPI_EVENT_FNKEY_F */ 179 22, /* 29 SONYPI_EVENT_FNKEY_S */ 180 23, /* 30 SONYPI_EVENT_FNKEY_B */ 181 24, /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */ 182 25, /* 32 SONYPI_EVENT_PKEY_P1 */ 183 26, /* 33 SONYPI_EVENT_PKEY_P2 */ 184 27, /* 34 SONYPI_EVENT_PKEY_P3 */ 185 28, /* 35 SONYPI_EVENT_BACK_PRESSED */ 186 -1, /* 36 SONYPI_EVENT_LID_CLOSED */ 187 -1, /* 37 SONYPI_EVENT_LID_OPENED */ 188 29, /* 38 SONYPI_EVENT_BLUETOOTH_ON */ 189 30, /* 39 SONYPI_EVENT_BLUETOOTH_OFF */ 190 31, /* 40 SONYPI_EVENT_HELP_PRESSED */ 191 32, /* 41 SONYPI_EVENT_FNKEY_ONLY */ 192 33, /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 193 34, /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */ 194 35, /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 195 36, /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 196 37, /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 197 38, /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 198 39, /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 199 40, /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 200 41, /* 50 SONYPI_EVENT_ZOOM_PRESSED */ 201 42, /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 202 43, /* 52 SONYPI_EVENT_MEYE_FACE */ 203 44, /* 53 SONYPI_EVENT_MEYE_OPPOSITE */ 204 45, /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */ 205 46, /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */ 206 -1, /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */ 207 -1, /* 57 SONYPI_EVENT_BATTERY_INSERT */ 208 -1, /* 58 SONYPI_EVENT_BATTERY_REMOVE */ 209 -1, /* 59 SONYPI_EVENT_FNKEY_RELEASED */ 210 47, /* 60 SONYPI_EVENT_WIRELESS_ON */ 211 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 212 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 213 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 214 }; 215 216 static int sony_laptop_input_keycode_map[] = { 217 KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */ 218 KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */ 219 KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 220 KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 221 KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */ 222 KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */ 223 KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */ 224 KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */ 225 KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */ 226 KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */ 227 KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */ 228 KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */ 229 KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */ 230 KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */ 231 KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ 232 KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ 233 KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ 234 KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ 235 KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ 236 KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ 237 KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ 238 KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ 239 KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */ 240 KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */ 241 KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */ 242 KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */ 243 KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */ 244 KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */ 245 KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */ 246 KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */ 247 KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */ 248 KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */ 249 KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */ 250 KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 251 KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */ 252 KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 253 KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 254 KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 255 KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 256 KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 257 KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 258 KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */ 259 BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 260 KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */ 261 KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */ 262 KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */ 263 KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ 264 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ 265 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ 266 KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ 267 KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 268 }; 269 270 /* release buttons after a short delay if pressed */ 271 static void do_sony_laptop_release_key(struct work_struct *work) 272 { 273 struct sony_laptop_keypress kp; 274 275 while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, 276 sizeof(kp)) == sizeof(kp)) { 277 msleep(10); 278 input_report_key(kp.dev, kp.key, 0); 279 input_sync(kp.dev); 280 } 281 } 282 static DECLARE_WORK(sony_laptop_release_key_work, 283 do_sony_laptop_release_key); 284 285 /* forward event to the input subsystem */ 286 static void sony_laptop_report_input_event(u8 event) 287 { 288 struct input_dev *jog_dev = sony_laptop_input.jog_dev; 289 struct input_dev *key_dev = sony_laptop_input.key_dev; 290 struct sony_laptop_keypress kp = { NULL }; 291 292 if (event == SONYPI_EVENT_FNKEY_RELEASED) { 293 /* Nothing, not all VAIOs generate this event */ 294 return; 295 } 296 297 /* report events */ 298 switch (event) { 299 /* jog_dev events */ 300 case SONYPI_EVENT_JOGDIAL_UP: 301 case SONYPI_EVENT_JOGDIAL_UP_PRESSED: 302 input_report_rel(jog_dev, REL_WHEEL, 1); 303 input_sync(jog_dev); 304 return; 305 306 case SONYPI_EVENT_JOGDIAL_DOWN: 307 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: 308 input_report_rel(jog_dev, REL_WHEEL, -1); 309 input_sync(jog_dev); 310 return; 311 312 /* key_dev events */ 313 case SONYPI_EVENT_JOGDIAL_PRESSED: 314 kp.key = BTN_MIDDLE; 315 kp.dev = jog_dev; 316 break; 317 318 default: 319 if (event >= ARRAY_SIZE(sony_laptop_input_index)) { 320 dprintk("sony_laptop_report_input_event, event not known: %d\n", event); 321 break; 322 } 323 if (sony_laptop_input_index[event] != -1) { 324 kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]]; 325 if (kp.key != KEY_UNKNOWN) 326 kp.dev = key_dev; 327 } 328 break; 329 } 330 331 if (kp.dev) { 332 input_report_key(kp.dev, kp.key, 1); 333 /* we emit the scancode so we can always remap the key */ 334 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 335 input_sync(kp.dev); 336 kfifo_put(sony_laptop_input.fifo, 337 (unsigned char *)&kp, sizeof(kp)); 338 339 if (!work_pending(&sony_laptop_release_key_work)) 340 queue_work(sony_laptop_input.wq, 341 &sony_laptop_release_key_work); 342 } else 343 dprintk("unknown input event %.2x\n", event); 344 } 345 346 static int sony_laptop_setup_input(struct acpi_device *acpi_device) 347 { 348 struct input_dev *jog_dev; 349 struct input_dev *key_dev; 350 int i; 351 int error; 352 353 /* don't run again if already initialized */ 354 if (atomic_add_return(1, &sony_laptop_input.users) > 1) 355 return 0; 356 357 /* kfifo */ 358 spin_lock_init(&sony_laptop_input.fifo_lock); 359 sony_laptop_input.fifo = 360 kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 361 &sony_laptop_input.fifo_lock); 362 if (IS_ERR(sony_laptop_input.fifo)) { 363 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 364 error = PTR_ERR(sony_laptop_input.fifo); 365 goto err_dec_users; 366 } 367 368 /* init workqueue */ 369 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); 370 if (!sony_laptop_input.wq) { 371 printk(KERN_ERR DRV_PFX 372 "Unabe to create workqueue.\n"); 373 error = -ENXIO; 374 goto err_free_kfifo; 375 } 376 377 /* input keys */ 378 key_dev = input_allocate_device(); 379 if (!key_dev) { 380 error = -ENOMEM; 381 goto err_destroy_wq; 382 } 383 384 key_dev->name = "Sony Vaio Keys"; 385 key_dev->id.bustype = BUS_ISA; 386 key_dev->id.vendor = PCI_VENDOR_ID_SONY; 387 key_dev->dev.parent = &acpi_device->dev; 388 389 /* Initialize the Input Drivers: special keys */ 390 set_bit(EV_KEY, key_dev->evbit); 391 set_bit(EV_MSC, key_dev->evbit); 392 set_bit(MSC_SCAN, key_dev->mscbit); 393 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 394 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 395 key_dev->keycode = &sony_laptop_input_keycode_map; 396 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { 397 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { 398 set_bit(sony_laptop_input_keycode_map[i], 399 key_dev->keybit); 400 } 401 } 402 403 error = input_register_device(key_dev); 404 if (error) 405 goto err_free_keydev; 406 407 sony_laptop_input.key_dev = key_dev; 408 409 /* jogdial */ 410 jog_dev = input_allocate_device(); 411 if (!jog_dev) { 412 error = -ENOMEM; 413 goto err_unregister_keydev; 414 } 415 416 jog_dev->name = "Sony Vaio Jogdial"; 417 jog_dev->id.bustype = BUS_ISA; 418 jog_dev->id.vendor = PCI_VENDOR_ID_SONY; 419 key_dev->dev.parent = &acpi_device->dev; 420 421 jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 422 jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); 423 jog_dev->relbit[0] = BIT_MASK(REL_WHEEL); 424 425 error = input_register_device(jog_dev); 426 if (error) 427 goto err_free_jogdev; 428 429 sony_laptop_input.jog_dev = jog_dev; 430 431 return 0; 432 433 err_free_jogdev: 434 input_free_device(jog_dev); 435 436 err_unregister_keydev: 437 input_unregister_device(key_dev); 438 /* to avoid kref underflow below at input_free_device */ 439 key_dev = NULL; 440 441 err_free_keydev: 442 input_free_device(key_dev); 443 444 err_destroy_wq: 445 destroy_workqueue(sony_laptop_input.wq); 446 447 err_free_kfifo: 448 kfifo_free(sony_laptop_input.fifo); 449 450 err_dec_users: 451 atomic_dec(&sony_laptop_input.users); 452 return error; 453 } 454 455 static void sony_laptop_remove_input(void) 456 { 457 /* cleanup only after the last user has gone */ 458 if (!atomic_dec_and_test(&sony_laptop_input.users)) 459 return; 460 461 /* flush workqueue first */ 462 flush_workqueue(sony_laptop_input.wq); 463 464 /* destroy input devs */ 465 input_unregister_device(sony_laptop_input.key_dev); 466 sony_laptop_input.key_dev = NULL; 467 468 if (sony_laptop_input.jog_dev) { 469 input_unregister_device(sony_laptop_input.jog_dev); 470 sony_laptop_input.jog_dev = NULL; 471 } 472 473 destroy_workqueue(sony_laptop_input.wq); 474 kfifo_free(sony_laptop_input.fifo); 475 } 476 477 /*********** Platform Device ***********/ 478 479 static atomic_t sony_pf_users = ATOMIC_INIT(0); 480 static struct platform_driver sony_pf_driver = { 481 .driver = { 482 .name = "sony-laptop", 483 .owner = THIS_MODULE, 484 } 485 }; 486 static struct platform_device *sony_pf_device; 487 488 static int sony_pf_add(void) 489 { 490 int ret = 0; 491 492 /* don't run again if already initialized */ 493 if (atomic_add_return(1, &sony_pf_users) > 1) 494 return 0; 495 496 ret = platform_driver_register(&sony_pf_driver); 497 if (ret) 498 goto out; 499 500 sony_pf_device = platform_device_alloc("sony-laptop", -1); 501 if (!sony_pf_device) { 502 ret = -ENOMEM; 503 goto out_platform_registered; 504 } 505 506 ret = platform_device_add(sony_pf_device); 507 if (ret) 508 goto out_platform_alloced; 509 510 return 0; 511 512 out_platform_alloced: 513 platform_device_put(sony_pf_device); 514 sony_pf_device = NULL; 515 out_platform_registered: 516 platform_driver_unregister(&sony_pf_driver); 517 out: 518 atomic_dec(&sony_pf_users); 519 return ret; 520 } 521 522 static void sony_pf_remove(void) 523 { 524 /* deregister only after the last user has gone */ 525 if (!atomic_dec_and_test(&sony_pf_users)) 526 return; 527 528 platform_device_del(sony_pf_device); 529 platform_device_put(sony_pf_device); 530 platform_driver_unregister(&sony_pf_driver); 531 } 532 533 /*********** SNC (SNY5001) Device ***********/ 534 535 /* the device uses 1-based values, while the backlight subsystem uses 536 0-based values */ 537 #define SONY_MAX_BRIGHTNESS 8 538 539 #define SNC_VALIDATE_IN 0 540 #define SNC_VALIDATE_OUT 1 541 542 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *, 543 char *); 544 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *, 545 const char *, size_t); 546 static int boolean_validate(const int, const int); 547 static int brightness_default_validate(const int, const int); 548 549 struct sony_nc_value { 550 char *name; /* name of the entry */ 551 char **acpiget; /* names of the ACPI get function */ 552 char **acpiset; /* names of the ACPI set function */ 553 int (*validate)(const int, const int); /* input/output validation */ 554 int value; /* current setting */ 555 int valid; /* Has ever been set */ 556 int debug; /* active only in debug mode ? */ 557 struct device_attribute devattr; /* sysfs atribute */ 558 }; 559 560 #define SNC_HANDLE_NAMES(_name, _values...) \ 561 static char *snc_##_name[] = { _values, NULL } 562 563 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \ 564 { \ 565 .name = __stringify(_name), \ 566 .acpiget = _getters, \ 567 .acpiset = _setters, \ 568 .validate = _validate, \ 569 .debug = _debug, \ 570 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \ 571 } 572 573 #define SNC_HANDLE_NULL { .name = NULL } 574 575 SNC_HANDLE_NAMES(fnkey_get, "GHKE"); 576 577 SNC_HANDLE_NAMES(brightness_def_get, "GPBR"); 578 SNC_HANDLE_NAMES(brightness_def_set, "SPBR"); 579 580 SNC_HANDLE_NAMES(cdpower_get, "GCDP"); 581 SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW"); 582 583 SNC_HANDLE_NAMES(audiopower_get, "GAZP"); 584 SNC_HANDLE_NAMES(audiopower_set, "AZPW"); 585 586 SNC_HANDLE_NAMES(lanpower_get, "GLNP"); 587 SNC_HANDLE_NAMES(lanpower_set, "LNPW"); 588 589 SNC_HANDLE_NAMES(lidstate_get, "GLID"); 590 591 SNC_HANDLE_NAMES(indicatorlamp_get, "GILS"); 592 SNC_HANDLE_NAMES(indicatorlamp_set, "SILS"); 593 594 SNC_HANDLE_NAMES(gainbass_get, "GMGB"); 595 SNC_HANDLE_NAMES(gainbass_set, "CMGB"); 596 597 SNC_HANDLE_NAMES(PID_get, "GPID"); 598 599 SNC_HANDLE_NAMES(CTR_get, "GCTR"); 600 SNC_HANDLE_NAMES(CTR_set, "SCTR"); 601 602 SNC_HANDLE_NAMES(PCR_get, "GPCR"); 603 SNC_HANDLE_NAMES(PCR_set, "SPCR"); 604 605 SNC_HANDLE_NAMES(CMI_get, "GCMI"); 606 SNC_HANDLE_NAMES(CMI_set, "SCMI"); 607 608 static struct sony_nc_value sony_nc_values[] = { 609 SNC_HANDLE(brightness_default, snc_brightness_def_get, 610 snc_brightness_def_set, brightness_default_validate, 0), 611 SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0), 612 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0), 613 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set, 614 boolean_validate, 0), 615 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, 616 boolean_validate, 1), 617 SNC_HANDLE(lidstate, snc_lidstate_get, NULL, 618 boolean_validate, 0), 619 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set, 620 boolean_validate, 0), 621 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set, 622 boolean_validate, 0), 623 /* unknown methods */ 624 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), 625 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), 626 SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1), 627 SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1), 628 SNC_HANDLE_NULL 629 }; 630 631 static acpi_handle sony_nc_acpi_handle; 632 static struct acpi_device *sony_nc_acpi_device = NULL; 633 634 /* 635 * acpi_evaluate_object wrappers 636 */ 637 static int acpi_callgetfunc(acpi_handle handle, char *name, int *result) 638 { 639 struct acpi_buffer output; 640 union acpi_object out_obj; 641 acpi_status status; 642 643 output.length = sizeof(out_obj); 644 output.pointer = &out_obj; 645 646 status = acpi_evaluate_object(handle, name, NULL, &output); 647 if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) { 648 *result = out_obj.integer.value; 649 return 0; 650 } 651 652 printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n"); 653 654 return -1; 655 } 656 657 static int acpi_callsetfunc(acpi_handle handle, char *name, int value, 658 int *result) 659 { 660 struct acpi_object_list params; 661 union acpi_object in_obj; 662 struct acpi_buffer output; 663 union acpi_object out_obj; 664 acpi_status status; 665 666 params.count = 1; 667 params.pointer = &in_obj; 668 in_obj.type = ACPI_TYPE_INTEGER; 669 in_obj.integer.value = value; 670 671 output.length = sizeof(out_obj); 672 output.pointer = &out_obj; 673 674 status = acpi_evaluate_object(handle, name, ¶ms, &output); 675 if (status == AE_OK) { 676 if (result != NULL) { 677 if (out_obj.type != ACPI_TYPE_INTEGER) { 678 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad " 679 "return type\n"); 680 return -1; 681 } 682 *result = out_obj.integer.value; 683 } 684 return 0; 685 } 686 687 printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n"); 688 689 return -1; 690 } 691 692 /* 693 * sony_nc_values input/output validate functions 694 */ 695 696 /* brightness_default_validate: 697 * 698 * manipulate input output values to keep consistency with the 699 * backlight framework for which brightness values are 0-based. 700 */ 701 static int brightness_default_validate(const int direction, const int value) 702 { 703 switch (direction) { 704 case SNC_VALIDATE_OUT: 705 return value - 1; 706 case SNC_VALIDATE_IN: 707 if (value >= 0 && value < SONY_MAX_BRIGHTNESS) 708 return value + 1; 709 } 710 return -EINVAL; 711 } 712 713 /* boolean_validate: 714 * 715 * on input validate boolean values 0/1, on output just pass the 716 * received value. 717 */ 718 static int boolean_validate(const int direction, const int value) 719 { 720 if (direction == SNC_VALIDATE_IN) { 721 if (value != 0 && value != 1) 722 return -EINVAL; 723 } 724 return value; 725 } 726 727 /* 728 * Sysfs show/store common to all sony_nc_values 729 */ 730 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr, 731 char *buffer) 732 { 733 int value; 734 struct sony_nc_value *item = 735 container_of(attr, struct sony_nc_value, devattr); 736 737 if (!*item->acpiget) 738 return -EIO; 739 740 if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0) 741 return -EIO; 742 743 if (item->validate) 744 value = item->validate(SNC_VALIDATE_OUT, value); 745 746 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 747 } 748 749 static ssize_t sony_nc_sysfs_store(struct device *dev, 750 struct device_attribute *attr, 751 const char *buffer, size_t count) 752 { 753 int value; 754 struct sony_nc_value *item = 755 container_of(attr, struct sony_nc_value, devattr); 756 757 if (!item->acpiset) 758 return -EIO; 759 760 if (count > 31) 761 return -EINVAL; 762 763 value = simple_strtoul(buffer, NULL, 10); 764 765 if (item->validate) 766 value = item->validate(SNC_VALIDATE_IN, value); 767 768 if (value < 0) 769 return value; 770 771 if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0) 772 return -EIO; 773 item->value = value; 774 item->valid = 1; 775 return count; 776 } 777 778 779 /* 780 * Backlight device 781 */ 782 static int sony_backlight_update_status(struct backlight_device *bd) 783 { 784 return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", 785 bd->props.brightness + 1, NULL); 786 } 787 788 static int sony_backlight_get_brightness(struct backlight_device *bd) 789 { 790 int value; 791 792 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) 793 return 0; 794 /* brightness levels are 1-based, while backlight ones are 0-based */ 795 return value - 1; 796 } 797 798 static struct backlight_device *sony_backlight_device; 799 static struct backlight_ops sony_backlight_ops = { 800 .update_status = sony_backlight_update_status, 801 .get_brightness = sony_backlight_get_brightness, 802 }; 803 804 /* 805 * New SNC-only Vaios event mapping to driver known keys 806 */ 807 struct sony_nc_event { 808 u8 data; 809 u8 event; 810 }; 811 812 static struct sony_nc_event *sony_nc_events; 813 814 /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence 815 * for Fn keys 816 */ 817 static int sony_nc_C_enable(const struct dmi_system_id *id) 818 { 819 int result = 0; 820 821 printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); 822 823 sony_nc_events = id->driver_data; 824 825 if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 826 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 827 || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 828 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 829 || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 830 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { 831 printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " 832 "functionalities may be missing\n"); 833 return 1; 834 } 835 return 0; 836 } 837 838 static struct sony_nc_event sony_C_events[] = { 839 { 0x81, SONYPI_EVENT_FNKEY_F1 }, 840 { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, 841 { 0x85, SONYPI_EVENT_FNKEY_F5 }, 842 { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, 843 { 0x86, SONYPI_EVENT_FNKEY_F6 }, 844 { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, 845 { 0x87, SONYPI_EVENT_FNKEY_F7 }, 846 { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, 847 { 0x8A, SONYPI_EVENT_FNKEY_F10 }, 848 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, 849 { 0x8C, SONYPI_EVENT_FNKEY_F12 }, 850 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 851 { 0, 0 }, 852 }; 853 854 /* SNC-only model map */ 855 static const struct dmi_system_id sony_nc_ids[] = { 856 { 857 .ident = "Sony Vaio FE Series", 858 .callback = sony_nc_C_enable, 859 .driver_data = sony_C_events, 860 .matches = { 861 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 862 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), 863 }, 864 }, 865 { 866 .ident = "Sony Vaio FZ Series", 867 .callback = sony_nc_C_enable, 868 .driver_data = sony_C_events, 869 .matches = { 870 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 871 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), 872 }, 873 }, 874 { 875 .ident = "Sony Vaio C Series", 876 .callback = sony_nc_C_enable, 877 .driver_data = sony_C_events, 878 .matches = { 879 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 880 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), 881 }, 882 }, 883 { 884 .ident = "Sony Vaio N Series", 885 .callback = sony_nc_C_enable, 886 .driver_data = sony_C_events, 887 .matches = { 888 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 889 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), 890 }, 891 }, 892 { } 893 }; 894 895 /* 896 * ACPI callbacks 897 */ 898 static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 899 { 900 struct sony_nc_event *evmap; 901 u32 ev = event; 902 int result; 903 904 if (ev == 0x92) { 905 /* read the key pressed from EC.GECR 906 * A call to SN07 with 0x0202 will do it as well respecting 907 * the current protocol on different OSes 908 * 909 * Note: the path for GECR may be 910 * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) 911 * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) 912 * 913 * TODO: we may want to do the same for the older GHKE -need 914 * dmi list- so this snippet may become one more callback. 915 */ 916 if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) 917 dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); 918 else 919 ev = result & 0xFF; 920 } 921 922 if (sony_nc_events) 923 for (evmap = sony_nc_events; evmap->event; evmap++) { 924 if (evmap->data == ev) { 925 ev = evmap->event; 926 break; 927 } 928 } 929 930 dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); 931 sony_laptop_report_input_event(ev); 932 acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); 933 } 934 935 static acpi_status sony_walk_callback(acpi_handle handle, u32 level, 936 void *context, void **return_value) 937 { 938 struct acpi_device_info *info; 939 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 940 941 if (ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) { 942 info = buffer.pointer; 943 944 printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", 945 (char *)&info->name, info->param_count); 946 947 kfree(buffer.pointer); 948 } 949 950 return AE_OK; 951 } 952 953 /* 954 * ACPI device 955 */ 956 static int sony_nc_resume(struct acpi_device *device) 957 { 958 struct sony_nc_value *item; 959 960 for (item = sony_nc_values; item->name; item++) { 961 int ret; 962 963 if (!item->valid) 964 continue; 965 ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, 966 item->value, NULL); 967 if (ret < 0) { 968 printk("%s: %d\n", __func__, ret); 969 break; 970 } 971 } 972 973 /* set the last requested brightness level */ 974 if (sony_backlight_device && 975 !sony_backlight_update_status(sony_backlight_device)) 976 printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); 977 978 /* re-initialize models with specific requirements */ 979 dmi_check_system(sony_nc_ids); 980 981 return 0; 982 } 983 984 static int sony_nc_add(struct acpi_device *device) 985 { 986 acpi_status status; 987 int result = 0; 988 acpi_handle handle; 989 struct sony_nc_value *item; 990 991 printk(KERN_INFO DRV_PFX "%s v%s.\n", 992 SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); 993 994 sony_nc_acpi_device = device; 995 strcpy(acpi_device_class(device), "sony/hotkey"); 996 997 sony_nc_acpi_handle = device->handle; 998 999 /* read device status */ 1000 result = acpi_bus_get_status(device); 1001 /* bail IFF the above call was successful and the device is not present */ 1002 if (!result && !device->status.present) { 1003 dprintk("Device not present\n"); 1004 result = -ENODEV; 1005 goto outwalk; 1006 } 1007 1008 if (debug) { 1009 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1010 1, sony_walk_callback, NULL, NULL); 1011 if (ACPI_FAILURE(status)) { 1012 printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); 1013 result = -ENODEV; 1014 goto outwalk; 1015 } 1016 } 1017 1018 /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1 1019 * should be respected as we already checked for the device presence above */ 1020 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) { 1021 dprintk("Invoking _INI\n"); 1022 if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI, 1023 NULL, NULL))) 1024 dprintk("_INI Method failed\n"); 1025 } 1026 1027 /* setup input devices and helper fifo */ 1028 result = sony_laptop_setup_input(device); 1029 if (result) { 1030 printk(KERN_ERR DRV_PFX 1031 "Unabe to create input devices.\n"); 1032 goto outwalk; 1033 } 1034 1035 status = acpi_install_notify_handler(sony_nc_acpi_handle, 1036 ACPI_DEVICE_NOTIFY, 1037 sony_acpi_notify, NULL); 1038 if (ACPI_FAILURE(status)) { 1039 printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status); 1040 result = -ENODEV; 1041 goto outinput; 1042 } 1043 1044 if (acpi_video_backlight_support()) { 1045 printk(KERN_INFO DRV_PFX "brightness ignored, must be " 1046 "controlled by ACPI video driver\n"); 1047 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", 1048 &handle))) { 1049 sony_backlight_device = backlight_device_register("sony", NULL, 1050 NULL, 1051 &sony_backlight_ops); 1052 1053 if (IS_ERR(sony_backlight_device)) { 1054 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); 1055 sony_backlight_device = NULL; 1056 } else { 1057 sony_backlight_device->props.brightness = 1058 sony_backlight_get_brightness 1059 (sony_backlight_device); 1060 sony_backlight_device->props.max_brightness = 1061 SONY_MAX_BRIGHTNESS - 1; 1062 } 1063 1064 } 1065 1066 /* initialize models with specific requirements */ 1067 dmi_check_system(sony_nc_ids); 1068 1069 result = sony_pf_add(); 1070 if (result) 1071 goto outbacklight; 1072 1073 /* create sony_pf sysfs attributes related to the SNC device */ 1074 for (item = sony_nc_values; item->name; ++item) { 1075 1076 if (!debug && item->debug) 1077 continue; 1078 1079 /* find the available acpiget as described in the DSDT */ 1080 for (; item->acpiget && *item->acpiget; ++item->acpiget) { 1081 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, 1082 *item->acpiget, 1083 &handle))) { 1084 dprintk("Found %s getter: %s\n", 1085 item->name, *item->acpiget); 1086 item->devattr.attr.mode |= S_IRUGO; 1087 break; 1088 } 1089 } 1090 1091 /* find the available acpiset as described in the DSDT */ 1092 for (; item->acpiset && *item->acpiset; ++item->acpiset) { 1093 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, 1094 *item->acpiset, 1095 &handle))) { 1096 dprintk("Found %s setter: %s\n", 1097 item->name, *item->acpiset); 1098 item->devattr.attr.mode |= S_IWUSR; 1099 break; 1100 } 1101 } 1102 1103 if (item->devattr.attr.mode != 0) { 1104 result = 1105 device_create_file(&sony_pf_device->dev, 1106 &item->devattr); 1107 if (result) 1108 goto out_sysfs; 1109 } 1110 } 1111 1112 return 0; 1113 1114 out_sysfs: 1115 for (item = sony_nc_values; item->name; ++item) { 1116 device_remove_file(&sony_pf_device->dev, &item->devattr); 1117 } 1118 sony_pf_remove(); 1119 1120 outbacklight: 1121 if (sony_backlight_device) 1122 backlight_device_unregister(sony_backlight_device); 1123 1124 status = acpi_remove_notify_handler(sony_nc_acpi_handle, 1125 ACPI_DEVICE_NOTIFY, 1126 sony_acpi_notify); 1127 if (ACPI_FAILURE(status)) 1128 printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n"); 1129 1130 outinput: 1131 sony_laptop_remove_input(); 1132 1133 outwalk: 1134 return result; 1135 } 1136 1137 static int sony_nc_remove(struct acpi_device *device, int type) 1138 { 1139 acpi_status status; 1140 struct sony_nc_value *item; 1141 1142 if (sony_backlight_device) 1143 backlight_device_unregister(sony_backlight_device); 1144 1145 sony_nc_acpi_device = NULL; 1146 1147 status = acpi_remove_notify_handler(sony_nc_acpi_handle, 1148 ACPI_DEVICE_NOTIFY, 1149 sony_acpi_notify); 1150 if (ACPI_FAILURE(status)) 1151 printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n"); 1152 1153 for (item = sony_nc_values; item->name; ++item) { 1154 device_remove_file(&sony_pf_device->dev, &item->devattr); 1155 } 1156 1157 sony_pf_remove(); 1158 sony_laptop_remove_input(); 1159 dprintk(SONY_NC_DRIVER_NAME " removed.\n"); 1160 1161 return 0; 1162 } 1163 1164 static const struct acpi_device_id sony_device_ids[] = { 1165 {SONY_NC_HID, 0}, 1166 {SONY_PIC_HID, 0}, 1167 {"", 0}, 1168 }; 1169 MODULE_DEVICE_TABLE(acpi, sony_device_ids); 1170 1171 static const struct acpi_device_id sony_nc_device_ids[] = { 1172 {SONY_NC_HID, 0}, 1173 {"", 0}, 1174 }; 1175 1176 static struct acpi_driver sony_nc_driver = { 1177 .name = SONY_NC_DRIVER_NAME, 1178 .class = SONY_NC_CLASS, 1179 .ids = sony_nc_device_ids, 1180 .owner = THIS_MODULE, 1181 .ops = { 1182 .add = sony_nc_add, 1183 .remove = sony_nc_remove, 1184 .resume = sony_nc_resume, 1185 }, 1186 }; 1187 1188 /*********** SPIC (SNY6001) Device ***********/ 1189 1190 #define SONYPI_DEVICE_TYPE1 0x00000001 1191 #define SONYPI_DEVICE_TYPE2 0x00000002 1192 #define SONYPI_DEVICE_TYPE3 0x00000004 1193 #define SONYPI_DEVICE_TYPE4 0x00000008 1194 1195 #define SONYPI_TYPE1_OFFSET 0x04 1196 #define SONYPI_TYPE2_OFFSET 0x12 1197 #define SONYPI_TYPE3_OFFSET 0x12 1198 #define SONYPI_TYPE4_OFFSET 0x12 1199 1200 struct sony_pic_ioport { 1201 struct acpi_resource_io io1; 1202 struct acpi_resource_io io2; 1203 struct list_head list; 1204 }; 1205 1206 struct sony_pic_irq { 1207 struct acpi_resource_irq irq; 1208 struct list_head list; 1209 }; 1210 1211 struct sonypi_eventtypes { 1212 u8 data; 1213 unsigned long mask; 1214 struct sonypi_event *events; 1215 }; 1216 1217 struct device_ctrl { 1218 int model; 1219 int (*handle_irq)(const u8, const u8); 1220 u16 evport_offset; 1221 u8 has_camera; 1222 u8 has_bluetooth; 1223 u8 has_wwan; 1224 struct sonypi_eventtypes *event_types; 1225 }; 1226 1227 struct sony_pic_dev { 1228 struct device_ctrl *control; 1229 struct acpi_device *acpi_dev; 1230 struct sony_pic_irq *cur_irq; 1231 struct sony_pic_ioport *cur_ioport; 1232 struct list_head interrupts; 1233 struct list_head ioports; 1234 struct mutex lock; 1235 u8 camera_power; 1236 u8 bluetooth_power; 1237 u8 wwan_power; 1238 }; 1239 1240 static struct sony_pic_dev spic_dev = { 1241 .interrupts = LIST_HEAD_INIT(spic_dev.interrupts), 1242 .ioports = LIST_HEAD_INIT(spic_dev.ioports), 1243 }; 1244 1245 /* Event masks */ 1246 #define SONYPI_JOGGER_MASK 0x00000001 1247 #define SONYPI_CAPTURE_MASK 0x00000002 1248 #define SONYPI_FNKEY_MASK 0x00000004 1249 #define SONYPI_BLUETOOTH_MASK 0x00000008 1250 #define SONYPI_PKEY_MASK 0x00000010 1251 #define SONYPI_BACK_MASK 0x00000020 1252 #define SONYPI_HELP_MASK 0x00000040 1253 #define SONYPI_LID_MASK 0x00000080 1254 #define SONYPI_ZOOM_MASK 0x00000100 1255 #define SONYPI_THUMBPHRASE_MASK 0x00000200 1256 #define SONYPI_MEYE_MASK 0x00000400 1257 #define SONYPI_MEMORYSTICK_MASK 0x00000800 1258 #define SONYPI_BATTERY_MASK 0x00001000 1259 #define SONYPI_WIRELESS_MASK 0x00002000 1260 1261 struct sonypi_event { 1262 u8 data; 1263 u8 event; 1264 }; 1265 1266 /* The set of possible button release events */ 1267 static struct sonypi_event sonypi_releaseev[] = { 1268 { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1269 { 0, 0 } 1270 }; 1271 1272 /* The set of possible jogger events */ 1273 static struct sonypi_event sonypi_joggerev[] = { 1274 { 0x1f, SONYPI_EVENT_JOGDIAL_UP }, 1275 { 0x01, SONYPI_EVENT_JOGDIAL_DOWN }, 1276 { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED }, 1277 { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED }, 1278 { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP }, 1279 { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN }, 1280 { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED }, 1281 { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED }, 1282 { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP }, 1283 { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN }, 1284 { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED }, 1285 { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED }, 1286 { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED }, 1287 { 0, 0 } 1288 }; 1289 1290 /* The set of possible capture button events */ 1291 static struct sonypi_event sonypi_captureev[] = { 1292 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, 1293 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, 1294 { 0x40, SONYPI_EVENT_CAPTURE_PRESSED }, 1295 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, 1296 { 0, 0 } 1297 }; 1298 1299 /* The set of possible fnkeys events */ 1300 static struct sonypi_event sonypi_fnkeyev[] = { 1301 { 0x10, SONYPI_EVENT_FNKEY_ESC }, 1302 { 0x11, SONYPI_EVENT_FNKEY_F1 }, 1303 { 0x12, SONYPI_EVENT_FNKEY_F2 }, 1304 { 0x13, SONYPI_EVENT_FNKEY_F3 }, 1305 { 0x14, SONYPI_EVENT_FNKEY_F4 }, 1306 { 0x15, SONYPI_EVENT_FNKEY_F5 }, 1307 { 0x16, SONYPI_EVENT_FNKEY_F6 }, 1308 { 0x17, SONYPI_EVENT_FNKEY_F7 }, 1309 { 0x18, SONYPI_EVENT_FNKEY_F8 }, 1310 { 0x19, SONYPI_EVENT_FNKEY_F9 }, 1311 { 0x1a, SONYPI_EVENT_FNKEY_F10 }, 1312 { 0x1b, SONYPI_EVENT_FNKEY_F11 }, 1313 { 0x1c, SONYPI_EVENT_FNKEY_F12 }, 1314 { 0x1f, SONYPI_EVENT_FNKEY_RELEASED }, 1315 { 0x21, SONYPI_EVENT_FNKEY_1 }, 1316 { 0x22, SONYPI_EVENT_FNKEY_2 }, 1317 { 0x31, SONYPI_EVENT_FNKEY_D }, 1318 { 0x32, SONYPI_EVENT_FNKEY_E }, 1319 { 0x33, SONYPI_EVENT_FNKEY_F }, 1320 { 0x34, SONYPI_EVENT_FNKEY_S }, 1321 { 0x35, SONYPI_EVENT_FNKEY_B }, 1322 { 0x36, SONYPI_EVENT_FNKEY_ONLY }, 1323 { 0, 0 } 1324 }; 1325 1326 /* The set of possible program key events */ 1327 static struct sonypi_event sonypi_pkeyev[] = { 1328 { 0x01, SONYPI_EVENT_PKEY_P1 }, 1329 { 0x02, SONYPI_EVENT_PKEY_P2 }, 1330 { 0x04, SONYPI_EVENT_PKEY_P3 }, 1331 { 0, 0 } 1332 }; 1333 1334 /* The set of possible bluetooth events */ 1335 static struct sonypi_event sonypi_blueev[] = { 1336 { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED }, 1337 { 0x59, SONYPI_EVENT_BLUETOOTH_ON }, 1338 { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF }, 1339 { 0, 0 } 1340 }; 1341 1342 /* The set of possible wireless events */ 1343 static struct sonypi_event sonypi_wlessev[] = { 1344 { 0x59, SONYPI_EVENT_WIRELESS_ON }, 1345 { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, 1346 { 0, 0 } 1347 }; 1348 1349 /* The set of possible back button events */ 1350 static struct sonypi_event sonypi_backev[] = { 1351 { 0x20, SONYPI_EVENT_BACK_PRESSED }, 1352 { 0, 0 } 1353 }; 1354 1355 /* The set of possible help button events */ 1356 static struct sonypi_event sonypi_helpev[] = { 1357 { 0x3b, SONYPI_EVENT_HELP_PRESSED }, 1358 { 0, 0 } 1359 }; 1360 1361 1362 /* The set of possible lid events */ 1363 static struct sonypi_event sonypi_lidev[] = { 1364 { 0x51, SONYPI_EVENT_LID_CLOSED }, 1365 { 0x50, SONYPI_EVENT_LID_OPENED }, 1366 { 0, 0 } 1367 }; 1368 1369 /* The set of possible zoom events */ 1370 static struct sonypi_event sonypi_zoomev[] = { 1371 { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, 1372 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, 1373 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, 1374 { 0, 0 } 1375 }; 1376 1377 /* The set of possible thumbphrase events */ 1378 static struct sonypi_event sonypi_thumbphraseev[] = { 1379 { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED }, 1380 { 0, 0 } 1381 }; 1382 1383 /* The set of possible motioneye camera events */ 1384 static struct sonypi_event sonypi_meyeev[] = { 1385 { 0x00, SONYPI_EVENT_MEYE_FACE }, 1386 { 0x01, SONYPI_EVENT_MEYE_OPPOSITE }, 1387 { 0, 0 } 1388 }; 1389 1390 /* The set of possible memorystick events */ 1391 static struct sonypi_event sonypi_memorystickev[] = { 1392 { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT }, 1393 { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT }, 1394 { 0, 0 } 1395 }; 1396 1397 /* The set of possible battery events */ 1398 static struct sonypi_event sonypi_batteryev[] = { 1399 { 0x20, SONYPI_EVENT_BATTERY_INSERT }, 1400 { 0x30, SONYPI_EVENT_BATTERY_REMOVE }, 1401 { 0, 0 } 1402 }; 1403 1404 static struct sonypi_eventtypes type1_events[] = { 1405 { 0, 0xffffffff, sonypi_releaseev }, 1406 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, 1407 { 0x30, SONYPI_LID_MASK, sonypi_lidev }, 1408 { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, 1409 { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, 1410 { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 1411 { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, 1412 { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1413 { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1414 { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1415 { 0 }, 1416 }; 1417 static struct sonypi_eventtypes type2_events[] = { 1418 { 0, 0xffffffff, sonypi_releaseev }, 1419 { 0x38, SONYPI_LID_MASK, sonypi_lidev }, 1420 { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, 1421 { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, 1422 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 1423 { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, 1424 { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1425 { 0x11, SONYPI_BACK_MASK, sonypi_backev }, 1426 { 0x21, SONYPI_HELP_MASK, sonypi_helpev }, 1427 { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, 1428 { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, 1429 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1430 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1431 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1432 { 0 }, 1433 }; 1434 static struct sonypi_eventtypes type3_events[] = { 1435 { 0, 0xffffffff, sonypi_releaseev }, 1436 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 1437 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, 1438 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1439 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1440 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1441 { 0 }, 1442 }; 1443 static struct sonypi_eventtypes type4_events[] = { 1444 { 0, 0xffffffff, sonypi_releaseev }, 1445 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 1446 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, 1447 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1448 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1449 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1450 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, 1451 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, 1452 { 0 }, 1453 }; 1454 1455 /* low level spic calls */ 1456 #define ITERATIONS_LONG 10000 1457 #define ITERATIONS_SHORT 10 1458 #define wait_on_command(command, iterations) { \ 1459 unsigned int n = iterations; \ 1460 while (--n && (command)) \ 1461 udelay(1); \ 1462 if (!n) \ 1463 dprintk("command failed at %s : %s (line %d)\n", \ 1464 __FILE__, __func__, __LINE__); \ 1465 } 1466 1467 static u8 sony_pic_call1(u8 dev) 1468 { 1469 u8 v1, v2; 1470 1471 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 1472 ITERATIONS_LONG); 1473 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 1474 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); 1475 v2 = inb_p(spic_dev.cur_ioport->io1.minimum); 1476 dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1); 1477 return v2; 1478 } 1479 1480 static u8 sony_pic_call2(u8 dev, u8 fn) 1481 { 1482 u8 v1; 1483 1484 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 1485 ITERATIONS_LONG); 1486 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 1487 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 1488 ITERATIONS_LONG); 1489 outb(fn, spic_dev.cur_ioport->io1.minimum); 1490 v1 = inb_p(spic_dev.cur_ioport->io1.minimum); 1491 dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1); 1492 return v1; 1493 } 1494 1495 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) 1496 { 1497 u8 v1; 1498 1499 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 1500 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 1501 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 1502 outb(fn, spic_dev.cur_ioport->io1.minimum); 1503 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 1504 outb(v, spic_dev.cur_ioport->io1.minimum); 1505 v1 = inb_p(spic_dev.cur_ioport->io1.minimum); 1506 dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", 1507 dev, fn, v, v1); 1508 return v1; 1509 } 1510 1511 /* 1512 * minidrivers for SPIC models 1513 */ 1514 static int type4_handle_irq(const u8 data_mask, const u8 ev) 1515 { 1516 /* 1517 * 0x31 could mean we have to take some extra action and wait for 1518 * the next irq for some Type4 models, it will generate a new 1519 * irq and we can read new data from the device: 1520 * - 0x5c and 0x5f requires 0xA0 1521 * - 0x61 requires 0xB3 1522 */ 1523 if (data_mask == 0x31) { 1524 if (ev == 0x5c || ev == 0x5f) 1525 sony_pic_call1(0xA0); 1526 else if (ev == 0x61) 1527 sony_pic_call1(0xB3); 1528 return 0; 1529 } 1530 return 1; 1531 } 1532 1533 static struct device_ctrl spic_types[] = { 1534 { 1535 .model = SONYPI_DEVICE_TYPE1, 1536 .handle_irq = NULL, 1537 .evport_offset = SONYPI_TYPE1_OFFSET, 1538 .event_types = type1_events, 1539 }, 1540 { 1541 .model = SONYPI_DEVICE_TYPE2, 1542 .handle_irq = NULL, 1543 .evport_offset = SONYPI_TYPE2_OFFSET, 1544 .event_types = type2_events, 1545 }, 1546 { 1547 .model = SONYPI_DEVICE_TYPE3, 1548 .handle_irq = NULL, 1549 .evport_offset = SONYPI_TYPE3_OFFSET, 1550 .event_types = type3_events, 1551 }, 1552 { 1553 .model = SONYPI_DEVICE_TYPE4, 1554 .handle_irq = type4_handle_irq, 1555 .evport_offset = SONYPI_TYPE4_OFFSET, 1556 .event_types = type4_events, 1557 }, 1558 }; 1559 1560 static void sony_pic_detect_device_type(struct sony_pic_dev *dev) 1561 { 1562 struct pci_dev *pcidev; 1563 1564 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1565 PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 1566 if (pcidev) { 1567 dev->control = &spic_types[0]; 1568 goto out; 1569 } 1570 1571 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1572 PCI_DEVICE_ID_INTEL_ICH6_1, NULL); 1573 if (pcidev) { 1574 dev->control = &spic_types[2]; 1575 goto out; 1576 } 1577 1578 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1579 PCI_DEVICE_ID_INTEL_ICH7_1, NULL); 1580 if (pcidev) { 1581 dev->control = &spic_types[3]; 1582 goto out; 1583 } 1584 1585 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1586 PCI_DEVICE_ID_INTEL_ICH8_4, NULL); 1587 if (pcidev) { 1588 dev->control = &spic_types[3]; 1589 goto out; 1590 } 1591 1592 /* default */ 1593 dev->control = &spic_types[1]; 1594 1595 out: 1596 if (pcidev) 1597 pci_dev_put(pcidev); 1598 1599 printk(KERN_INFO DRV_PFX "detected Type%d model\n", 1600 dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : 1601 dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 1602 dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); 1603 } 1604 1605 /* camera tests and poweron/poweroff */ 1606 #define SONYPI_CAMERA_PICTURE 5 1607 #define SONYPI_CAMERA_CONTROL 0x10 1608 1609 #define SONYPI_CAMERA_BRIGHTNESS 0 1610 #define SONYPI_CAMERA_CONTRAST 1 1611 #define SONYPI_CAMERA_HUE 2 1612 #define SONYPI_CAMERA_COLOR 3 1613 #define SONYPI_CAMERA_SHARPNESS 4 1614 1615 #define SONYPI_CAMERA_EXPOSURE_MASK 0xC 1616 #define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3 1617 #define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30 1618 #define SONYPI_CAMERA_MUTE_MASK 0x40 1619 1620 /* the rest don't need a loop until not 0xff */ 1621 #define SONYPI_CAMERA_AGC 6 1622 #define SONYPI_CAMERA_AGC_MASK 0x30 1623 #define SONYPI_CAMERA_SHUTTER_MASK 0x7 1624 1625 #define SONYPI_CAMERA_SHUTDOWN_REQUEST 7 1626 #define SONYPI_CAMERA_CONTROL 0x10 1627 1628 #define SONYPI_CAMERA_STATUS 7 1629 #define SONYPI_CAMERA_STATUS_READY 0x2 1630 #define SONYPI_CAMERA_STATUS_POSITION 0x4 1631 1632 #define SONYPI_DIRECTION_BACKWARDS 0x4 1633 1634 #define SONYPI_CAMERA_REVISION 8 1635 #define SONYPI_CAMERA_ROMVERSION 9 1636 1637 static int __sony_pic_camera_ready(void) 1638 { 1639 u8 v; 1640 1641 v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS); 1642 return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY)); 1643 } 1644 1645 static int __sony_pic_camera_off(void) 1646 { 1647 if (!camera) { 1648 printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); 1649 return -ENODEV; 1650 } 1651 1652 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, 1653 SONYPI_CAMERA_MUTE_MASK), 1654 ITERATIONS_SHORT); 1655 1656 if (spic_dev.camera_power) { 1657 sony_pic_call2(0x91, 0); 1658 spic_dev.camera_power = 0; 1659 } 1660 return 0; 1661 } 1662 1663 static int __sony_pic_camera_on(void) 1664 { 1665 int i, j, x; 1666 1667 if (!camera) { 1668 printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); 1669 return -ENODEV; 1670 } 1671 1672 if (spic_dev.camera_power) 1673 return 0; 1674 1675 for (j = 5; j > 0; j--) { 1676 1677 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++) 1678 msleep(10); 1679 sony_pic_call1(0x93); 1680 1681 for (i = 400; i > 0; i--) { 1682 if (__sony_pic_camera_ready()) 1683 break; 1684 msleep(10); 1685 } 1686 if (i) 1687 break; 1688 } 1689 1690 if (j == 0) { 1691 printk(KERN_WARNING DRV_PFX "failed to power on camera\n"); 1692 return -ENODEV; 1693 } 1694 1695 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL, 1696 0x5a), 1697 ITERATIONS_SHORT); 1698 1699 spic_dev.camera_power = 1; 1700 return 0; 1701 } 1702 1703 /* External camera command (exported to the motion eye v4l driver) */ 1704 int sony_pic_camera_command(int command, u8 value) 1705 { 1706 if (!camera) 1707 return -EIO; 1708 1709 mutex_lock(&spic_dev.lock); 1710 1711 switch (command) { 1712 case SONY_PIC_COMMAND_SETCAMERA: 1713 if (value) 1714 __sony_pic_camera_on(); 1715 else 1716 __sony_pic_camera_off(); 1717 break; 1718 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS: 1719 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value), 1720 ITERATIONS_SHORT); 1721 break; 1722 case SONY_PIC_COMMAND_SETCAMERACONTRAST: 1723 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value), 1724 ITERATIONS_SHORT); 1725 break; 1726 case SONY_PIC_COMMAND_SETCAMERAHUE: 1727 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value), 1728 ITERATIONS_SHORT); 1729 break; 1730 case SONY_PIC_COMMAND_SETCAMERACOLOR: 1731 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value), 1732 ITERATIONS_SHORT); 1733 break; 1734 case SONY_PIC_COMMAND_SETCAMERASHARPNESS: 1735 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value), 1736 ITERATIONS_SHORT); 1737 break; 1738 case SONY_PIC_COMMAND_SETCAMERAPICTURE: 1739 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value), 1740 ITERATIONS_SHORT); 1741 break; 1742 case SONY_PIC_COMMAND_SETCAMERAAGC: 1743 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value), 1744 ITERATIONS_SHORT); 1745 break; 1746 default: 1747 printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n", 1748 command); 1749 break; 1750 } 1751 mutex_unlock(&spic_dev.lock); 1752 return 0; 1753 } 1754 EXPORT_SYMBOL(sony_pic_camera_command); 1755 1756 /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ 1757 static void sony_pic_set_wwanpower(u8 state) 1758 { 1759 state = !!state; 1760 mutex_lock(&spic_dev.lock); 1761 if (spic_dev.wwan_power == state) { 1762 mutex_unlock(&spic_dev.lock); 1763 return; 1764 } 1765 sony_pic_call2(0xB0, state); 1766 spic_dev.wwan_power = state; 1767 mutex_unlock(&spic_dev.lock); 1768 } 1769 1770 static ssize_t sony_pic_wwanpower_store(struct device *dev, 1771 struct device_attribute *attr, 1772 const char *buffer, size_t count) 1773 { 1774 unsigned long value; 1775 if (count > 31) 1776 return -EINVAL; 1777 1778 value = simple_strtoul(buffer, NULL, 10); 1779 sony_pic_set_wwanpower(value); 1780 1781 return count; 1782 } 1783 1784 static ssize_t sony_pic_wwanpower_show(struct device *dev, 1785 struct device_attribute *attr, char *buffer) 1786 { 1787 ssize_t count; 1788 mutex_lock(&spic_dev.lock); 1789 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power); 1790 mutex_unlock(&spic_dev.lock); 1791 return count; 1792 } 1793 1794 /* bluetooth subsystem power state */ 1795 static void __sony_pic_set_bluetoothpower(u8 state) 1796 { 1797 state = !!state; 1798 if (spic_dev.bluetooth_power == state) 1799 return; 1800 sony_pic_call2(0x96, state); 1801 sony_pic_call1(0x82); 1802 spic_dev.bluetooth_power = state; 1803 } 1804 1805 static ssize_t sony_pic_bluetoothpower_store(struct device *dev, 1806 struct device_attribute *attr, 1807 const char *buffer, size_t count) 1808 { 1809 unsigned long value; 1810 if (count > 31) 1811 return -EINVAL; 1812 1813 value = simple_strtoul(buffer, NULL, 10); 1814 mutex_lock(&spic_dev.lock); 1815 __sony_pic_set_bluetoothpower(value); 1816 mutex_unlock(&spic_dev.lock); 1817 1818 return count; 1819 } 1820 1821 static ssize_t sony_pic_bluetoothpower_show(struct device *dev, 1822 struct device_attribute *attr, char *buffer) 1823 { 1824 ssize_t count = 0; 1825 mutex_lock(&spic_dev.lock); 1826 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power); 1827 mutex_unlock(&spic_dev.lock); 1828 return count; 1829 } 1830 1831 /* fan speed */ 1832 /* FAN0 information (reverse engineered from ACPI tables) */ 1833 #define SONY_PIC_FAN0_STATUS 0x93 1834 static int sony_pic_set_fanspeed(unsigned long value) 1835 { 1836 return ec_write(SONY_PIC_FAN0_STATUS, value); 1837 } 1838 1839 static int sony_pic_get_fanspeed(u8 *value) 1840 { 1841 return ec_read(SONY_PIC_FAN0_STATUS, value); 1842 } 1843 1844 static ssize_t sony_pic_fanspeed_store(struct device *dev, 1845 struct device_attribute *attr, 1846 const char *buffer, size_t count) 1847 { 1848 unsigned long value; 1849 if (count > 31) 1850 return -EINVAL; 1851 1852 value = simple_strtoul(buffer, NULL, 10); 1853 if (sony_pic_set_fanspeed(value)) 1854 return -EIO; 1855 1856 return count; 1857 } 1858 1859 static ssize_t sony_pic_fanspeed_show(struct device *dev, 1860 struct device_attribute *attr, char *buffer) 1861 { 1862 u8 value = 0; 1863 if (sony_pic_get_fanspeed(&value)) 1864 return -EIO; 1865 1866 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 1867 } 1868 1869 #define SPIC_ATTR(_name, _mode) \ 1870 struct device_attribute spic_attr_##_name = __ATTR(_name, \ 1871 _mode, sony_pic_## _name ##_show, \ 1872 sony_pic_## _name ##_store) 1873 1874 static SPIC_ATTR(bluetoothpower, 0644); 1875 static SPIC_ATTR(wwanpower, 0644); 1876 static SPIC_ATTR(fanspeed, 0644); 1877 1878 static struct attribute *spic_attributes[] = { 1879 &spic_attr_bluetoothpower.attr, 1880 &spic_attr_wwanpower.attr, 1881 &spic_attr_fanspeed.attr, 1882 NULL 1883 }; 1884 1885 static struct attribute_group spic_attribute_group = { 1886 .attrs = spic_attributes 1887 }; 1888 1889 /******** SONYPI compatibility **********/ 1890 #ifdef CONFIG_SONYPI_COMPAT 1891 1892 /* battery / brightness / temperature addresses */ 1893 #define SONYPI_BAT_FLAGS 0x81 1894 #define SONYPI_LCD_LIGHT 0x96 1895 #define SONYPI_BAT1_PCTRM 0xa0 1896 #define SONYPI_BAT1_LEFT 0xa2 1897 #define SONYPI_BAT1_MAXRT 0xa4 1898 #define SONYPI_BAT2_PCTRM 0xa8 1899 #define SONYPI_BAT2_LEFT 0xaa 1900 #define SONYPI_BAT2_MAXRT 0xac 1901 #define SONYPI_BAT1_MAXTK 0xb0 1902 #define SONYPI_BAT1_FULL 0xb2 1903 #define SONYPI_BAT2_MAXTK 0xb8 1904 #define SONYPI_BAT2_FULL 0xba 1905 #define SONYPI_TEMP_STATUS 0xC1 1906 1907 struct sonypi_compat_s { 1908 struct fasync_struct *fifo_async; 1909 struct kfifo *fifo; 1910 spinlock_t fifo_lock; 1911 wait_queue_head_t fifo_proc_list; 1912 atomic_t open_count; 1913 }; 1914 static struct sonypi_compat_s sonypi_compat = { 1915 .open_count = ATOMIC_INIT(0), 1916 }; 1917 1918 static int sonypi_misc_fasync(int fd, struct file *filp, int on) 1919 { 1920 return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async); 1921 } 1922 1923 static int sonypi_misc_release(struct inode *inode, struct file *file) 1924 { 1925 atomic_dec(&sonypi_compat.open_count); 1926 return 0; 1927 } 1928 1929 static int sonypi_misc_open(struct inode *inode, struct file *file) 1930 { 1931 /* Flush input queue on first open */ 1932 lock_kernel(); 1933 if (atomic_inc_return(&sonypi_compat.open_count) == 1) 1934 kfifo_reset(sonypi_compat.fifo); 1935 unlock_kernel(); 1936 return 0; 1937 } 1938 1939 static ssize_t sonypi_misc_read(struct file *file, char __user *buf, 1940 size_t count, loff_t *pos) 1941 { 1942 ssize_t ret; 1943 unsigned char c; 1944 1945 if ((kfifo_len(sonypi_compat.fifo) == 0) && 1946 (file->f_flags & O_NONBLOCK)) 1947 return -EAGAIN; 1948 1949 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, 1950 kfifo_len(sonypi_compat.fifo) != 0); 1951 if (ret) 1952 return ret; 1953 1954 while (ret < count && 1955 (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { 1956 if (put_user(c, buf++)) 1957 return -EFAULT; 1958 ret++; 1959 } 1960 1961 if (ret > 0) { 1962 struct inode *inode = file->f_path.dentry->d_inode; 1963 inode->i_atime = current_fs_time(inode->i_sb); 1964 } 1965 1966 return ret; 1967 } 1968 1969 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) 1970 { 1971 poll_wait(file, &sonypi_compat.fifo_proc_list, wait); 1972 if (kfifo_len(sonypi_compat.fifo)) 1973 return POLLIN | POLLRDNORM; 1974 return 0; 1975 } 1976 1977 static int ec_read16(u8 addr, u16 *value) 1978 { 1979 u8 val_lb, val_hb; 1980 if (ec_read(addr, &val_lb)) 1981 return -1; 1982 if (ec_read(addr + 1, &val_hb)) 1983 return -1; 1984 *value = val_lb | (val_hb << 8); 1985 return 0; 1986 } 1987 1988 static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 1989 unsigned int cmd, unsigned long arg) 1990 { 1991 int ret = 0; 1992 void __user *argp = (void __user *)arg; 1993 u8 val8; 1994 u16 val16; 1995 int value; 1996 1997 mutex_lock(&spic_dev.lock); 1998 switch (cmd) { 1999 case SONYPI_IOCGBRT: 2000 if (sony_backlight_device == NULL) { 2001 ret = -EIO; 2002 break; 2003 } 2004 if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) { 2005 ret = -EIO; 2006 break; 2007 } 2008 val8 = ((value & 0xff) - 1) << 5; 2009 if (copy_to_user(argp, &val8, sizeof(val8))) 2010 ret = -EFAULT; 2011 break; 2012 case SONYPI_IOCSBRT: 2013 if (sony_backlight_device == NULL) { 2014 ret = -EIO; 2015 break; 2016 } 2017 if (copy_from_user(&val8, argp, sizeof(val8))) { 2018 ret = -EFAULT; 2019 break; 2020 } 2021 if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", 2022 (val8 >> 5) + 1, NULL)) { 2023 ret = -EIO; 2024 break; 2025 } 2026 /* sync the backlight device status */ 2027 sony_backlight_device->props.brightness = 2028 sony_backlight_get_brightness(sony_backlight_device); 2029 break; 2030 case SONYPI_IOCGBAT1CAP: 2031 if (ec_read16(SONYPI_BAT1_FULL, &val16)) { 2032 ret = -EIO; 2033 break; 2034 } 2035 if (copy_to_user(argp, &val16, sizeof(val16))) 2036 ret = -EFAULT; 2037 break; 2038 case SONYPI_IOCGBAT1REM: 2039 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) { 2040 ret = -EIO; 2041 break; 2042 } 2043 if (copy_to_user(argp, &val16, sizeof(val16))) 2044 ret = -EFAULT; 2045 break; 2046 case SONYPI_IOCGBAT2CAP: 2047 if (ec_read16(SONYPI_BAT2_FULL, &val16)) { 2048 ret = -EIO; 2049 break; 2050 } 2051 if (copy_to_user(argp, &val16, sizeof(val16))) 2052 ret = -EFAULT; 2053 break; 2054 case SONYPI_IOCGBAT2REM: 2055 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) { 2056 ret = -EIO; 2057 break; 2058 } 2059 if (copy_to_user(argp, &val16, sizeof(val16))) 2060 ret = -EFAULT; 2061 break; 2062 case SONYPI_IOCGBATFLAGS: 2063 if (ec_read(SONYPI_BAT_FLAGS, &val8)) { 2064 ret = -EIO; 2065 break; 2066 } 2067 val8 &= 0x07; 2068 if (copy_to_user(argp, &val8, sizeof(val8))) 2069 ret = -EFAULT; 2070 break; 2071 case SONYPI_IOCGBLUE: 2072 val8 = spic_dev.bluetooth_power; 2073 if (copy_to_user(argp, &val8, sizeof(val8))) 2074 ret = -EFAULT; 2075 break; 2076 case SONYPI_IOCSBLUE: 2077 if (copy_from_user(&val8, argp, sizeof(val8))) { 2078 ret = -EFAULT; 2079 break; 2080 } 2081 __sony_pic_set_bluetoothpower(val8); 2082 break; 2083 /* FAN Controls */ 2084 case SONYPI_IOCGFAN: 2085 if (sony_pic_get_fanspeed(&val8)) { 2086 ret = -EIO; 2087 break; 2088 } 2089 if (copy_to_user(argp, &val8, sizeof(val8))) 2090 ret = -EFAULT; 2091 break; 2092 case SONYPI_IOCSFAN: 2093 if (copy_from_user(&val8, argp, sizeof(val8))) { 2094 ret = -EFAULT; 2095 break; 2096 } 2097 if (sony_pic_set_fanspeed(val8)) 2098 ret = -EIO; 2099 break; 2100 /* GET Temperature (useful under APM) */ 2101 case SONYPI_IOCGTEMP: 2102 if (ec_read(SONYPI_TEMP_STATUS, &val8)) { 2103 ret = -EIO; 2104 break; 2105 } 2106 if (copy_to_user(argp, &val8, sizeof(val8))) 2107 ret = -EFAULT; 2108 break; 2109 default: 2110 ret = -EINVAL; 2111 } 2112 mutex_unlock(&spic_dev.lock); 2113 return ret; 2114 } 2115 2116 static const struct file_operations sonypi_misc_fops = { 2117 .owner = THIS_MODULE, 2118 .read = sonypi_misc_read, 2119 .poll = sonypi_misc_poll, 2120 .open = sonypi_misc_open, 2121 .release = sonypi_misc_release, 2122 .fasync = sonypi_misc_fasync, 2123 .ioctl = sonypi_misc_ioctl, 2124 }; 2125 2126 static struct miscdevice sonypi_misc_device = { 2127 .minor = MISC_DYNAMIC_MINOR, 2128 .name = "sonypi", 2129 .fops = &sonypi_misc_fops, 2130 }; 2131 2132 static void sonypi_compat_report_event(u8 event) 2133 { 2134 kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); 2135 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); 2136 wake_up_interruptible(&sonypi_compat.fifo_proc_list); 2137 } 2138 2139 static int sonypi_compat_init(void) 2140 { 2141 int error; 2142 2143 spin_lock_init(&sonypi_compat.fifo_lock); 2144 sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, 2145 &sonypi_compat.fifo_lock); 2146 if (IS_ERR(sonypi_compat.fifo)) { 2147 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 2148 return PTR_ERR(sonypi_compat.fifo); 2149 } 2150 2151 init_waitqueue_head(&sonypi_compat.fifo_proc_list); 2152 2153 if (minor != -1) 2154 sonypi_misc_device.minor = minor; 2155 error = misc_register(&sonypi_misc_device); 2156 if (error) { 2157 printk(KERN_ERR DRV_PFX "misc_register failed\n"); 2158 goto err_free_kfifo; 2159 } 2160 if (minor == -1) 2161 printk(KERN_INFO DRV_PFX "device allocated minor is %d\n", 2162 sonypi_misc_device.minor); 2163 2164 return 0; 2165 2166 err_free_kfifo: 2167 kfifo_free(sonypi_compat.fifo); 2168 return error; 2169 } 2170 2171 static void sonypi_compat_exit(void) 2172 { 2173 misc_deregister(&sonypi_misc_device); 2174 kfifo_free(sonypi_compat.fifo); 2175 } 2176 #else 2177 static int sonypi_compat_init(void) { return 0; } 2178 static void sonypi_compat_exit(void) { } 2179 static void sonypi_compat_report_event(u8 event) { } 2180 #endif /* CONFIG_SONYPI_COMPAT */ 2181 2182 /* 2183 * ACPI callbacks 2184 */ 2185 static acpi_status 2186 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) 2187 { 2188 u32 i; 2189 struct sony_pic_dev *dev = (struct sony_pic_dev *)context; 2190 2191 switch (resource->type) { 2192 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 2193 { 2194 /* start IO enumeration */ 2195 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); 2196 if (!ioport) 2197 return AE_ERROR; 2198 2199 list_add(&ioport->list, &dev->ioports); 2200 return AE_OK; 2201 } 2202 2203 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 2204 /* end IO enumeration */ 2205 return AE_OK; 2206 2207 case ACPI_RESOURCE_TYPE_IRQ: 2208 { 2209 struct acpi_resource_irq *p = &resource->data.irq; 2210 struct sony_pic_irq *interrupt = NULL; 2211 if (!p || !p->interrupt_count) { 2212 /* 2213 * IRQ descriptors may have no IRQ# bits set, 2214 * particularly those those w/ _STA disabled 2215 */ 2216 dprintk("Blank IRQ resource\n"); 2217 return AE_OK; 2218 } 2219 for (i = 0; i < p->interrupt_count; i++) { 2220 if (!p->interrupts[i]) { 2221 printk(KERN_WARNING DRV_PFX 2222 "Invalid IRQ %d\n", 2223 p->interrupts[i]); 2224 continue; 2225 } 2226 interrupt = kzalloc(sizeof(*interrupt), 2227 GFP_KERNEL); 2228 if (!interrupt) 2229 return AE_ERROR; 2230 2231 list_add(&interrupt->list, &dev->interrupts); 2232 interrupt->irq.triggering = p->triggering; 2233 interrupt->irq.polarity = p->polarity; 2234 interrupt->irq.sharable = p->sharable; 2235 interrupt->irq.interrupt_count = 1; 2236 interrupt->irq.interrupts[0] = p->interrupts[i]; 2237 } 2238 return AE_OK; 2239 } 2240 case ACPI_RESOURCE_TYPE_IO: 2241 { 2242 struct acpi_resource_io *io = &resource->data.io; 2243 struct sony_pic_ioport *ioport = 2244 list_first_entry(&dev->ioports, struct sony_pic_ioport, list); 2245 if (!io) { 2246 dprintk("Blank IO resource\n"); 2247 return AE_OK; 2248 } 2249 2250 if (!ioport->io1.minimum) { 2251 memcpy(&ioport->io1, io, sizeof(*io)); 2252 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum, 2253 ioport->io1.address_length); 2254 } 2255 else if (!ioport->io2.minimum) { 2256 memcpy(&ioport->io2, io, sizeof(*io)); 2257 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum, 2258 ioport->io2.address_length); 2259 } 2260 else { 2261 printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); 2262 return AE_ERROR; 2263 } 2264 return AE_OK; 2265 } 2266 default: 2267 dprintk("Resource %d isn't an IRQ nor an IO port\n", 2268 resource->type); 2269 2270 case ACPI_RESOURCE_TYPE_END_TAG: 2271 return AE_OK; 2272 } 2273 return AE_CTRL_TERMINATE; 2274 } 2275 2276 static int sony_pic_possible_resources(struct acpi_device *device) 2277 { 2278 int result = 0; 2279 acpi_status status = AE_OK; 2280 2281 if (!device) 2282 return -EINVAL; 2283 2284 /* get device status */ 2285 /* see acpi_pci_link_get_current acpi_pci_link_get_possible */ 2286 dprintk("Evaluating _STA\n"); 2287 result = acpi_bus_get_status(device); 2288 if (result) { 2289 printk(KERN_WARNING DRV_PFX "Unable to read status\n"); 2290 goto end; 2291 } 2292 2293 if (!device->status.enabled) 2294 dprintk("Device disabled\n"); 2295 else 2296 dprintk("Device enabled\n"); 2297 2298 /* 2299 * Query and parse 'method' 2300 */ 2301 dprintk("Evaluating %s\n", METHOD_NAME__PRS); 2302 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS, 2303 sony_pic_read_possible_resource, &spic_dev); 2304 if (ACPI_FAILURE(status)) { 2305 printk(KERN_WARNING DRV_PFX 2306 "Failure evaluating %s\n", 2307 METHOD_NAME__PRS); 2308 result = -ENODEV; 2309 } 2310 end: 2311 return result; 2312 } 2313 2314 /* 2315 * Disable the spic device by calling its _DIS method 2316 */ 2317 static int sony_pic_disable(struct acpi_device *device) 2318 { 2319 acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL, 2320 NULL); 2321 2322 if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND) 2323 return -ENXIO; 2324 2325 dprintk("Device disabled\n"); 2326 return 0; 2327 } 2328 2329 2330 /* 2331 * Based on drivers/acpi/pci_link.c:acpi_pci_link_set 2332 * 2333 * Call _SRS to set current resources 2334 */ 2335 static int sony_pic_enable(struct acpi_device *device, 2336 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq) 2337 { 2338 acpi_status status; 2339 int result = 0; 2340 /* Type 1 resource layout is: 2341 * IO 2342 * IO 2343 * IRQNoFlags 2344 * End 2345 * 2346 * Type 2 and 3 resource layout is: 2347 * IO 2348 * IRQNoFlags 2349 * End 2350 */ 2351 struct { 2352 struct acpi_resource res1; 2353 struct acpi_resource res2; 2354 struct acpi_resource res3; 2355 struct acpi_resource res4; 2356 } *resource; 2357 struct acpi_buffer buffer = { 0, NULL }; 2358 2359 if (!ioport || !irq) 2360 return -EINVAL; 2361 2362 /* init acpi_buffer */ 2363 resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL); 2364 if (!resource) 2365 return -ENOMEM; 2366 2367 buffer.length = sizeof(*resource) + 1; 2368 buffer.pointer = resource; 2369 2370 /* setup Type 1 resources */ 2371 if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) { 2372 2373 /* setup io resources */ 2374 resource->res1.type = ACPI_RESOURCE_TYPE_IO; 2375 resource->res1.length = sizeof(struct acpi_resource); 2376 memcpy(&resource->res1.data.io, &ioport->io1, 2377 sizeof(struct acpi_resource_io)); 2378 2379 resource->res2.type = ACPI_RESOURCE_TYPE_IO; 2380 resource->res2.length = sizeof(struct acpi_resource); 2381 memcpy(&resource->res2.data.io, &ioport->io2, 2382 sizeof(struct acpi_resource_io)); 2383 2384 /* setup irq resource */ 2385 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ; 2386 resource->res3.length = sizeof(struct acpi_resource); 2387 memcpy(&resource->res3.data.irq, &irq->irq, 2388 sizeof(struct acpi_resource_irq)); 2389 /* we requested a shared irq */ 2390 resource->res3.data.irq.sharable = ACPI_SHARED; 2391 2392 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG; 2393 2394 } 2395 /* setup Type 2/3 resources */ 2396 else { 2397 /* setup io resource */ 2398 resource->res1.type = ACPI_RESOURCE_TYPE_IO; 2399 resource->res1.length = sizeof(struct acpi_resource); 2400 memcpy(&resource->res1.data.io, &ioport->io1, 2401 sizeof(struct acpi_resource_io)); 2402 2403 /* setup irq resource */ 2404 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ; 2405 resource->res2.length = sizeof(struct acpi_resource); 2406 memcpy(&resource->res2.data.irq, &irq->irq, 2407 sizeof(struct acpi_resource_irq)); 2408 /* we requested a shared irq */ 2409 resource->res2.data.irq.sharable = ACPI_SHARED; 2410 2411 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG; 2412 } 2413 2414 /* Attempt to set the resource */ 2415 dprintk("Evaluating _SRS\n"); 2416 status = acpi_set_current_resources(device->handle, &buffer); 2417 2418 /* check for total failure */ 2419 if (ACPI_FAILURE(status)) { 2420 printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n"); 2421 result = -ENODEV; 2422 goto end; 2423 } 2424 2425 /* Necessary device initializations calls (from sonypi) */ 2426 sony_pic_call1(0x82); 2427 sony_pic_call2(0x81, 0xff); 2428 sony_pic_call1(compat ? 0x92 : 0x82); 2429 2430 end: 2431 kfree(resource); 2432 return result; 2433 } 2434 2435 /***************** 2436 * 2437 * ISR: some event is available 2438 * 2439 *****************/ 2440 static irqreturn_t sony_pic_irq(int irq, void *dev_id) 2441 { 2442 int i, j; 2443 u8 ev = 0; 2444 u8 data_mask = 0; 2445 u8 device_event = 0; 2446 2447 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 2448 2449 ev = inb_p(dev->cur_ioport->io1.minimum); 2450 if (dev->cur_ioport->io2.minimum) 2451 data_mask = inb_p(dev->cur_ioport->io2.minimum); 2452 else 2453 data_mask = inb_p(dev->cur_ioport->io1.minimum + 2454 dev->control->evport_offset); 2455 2456 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2457 ev, data_mask, dev->cur_ioport->io1.minimum, 2458 dev->control->evport_offset); 2459 2460 if (ev == 0x00 || ev == 0xff) 2461 return IRQ_HANDLED; 2462 2463 for (i = 0; dev->control->event_types[i].mask; i++) { 2464 2465 if ((data_mask & dev->control->event_types[i].data) != 2466 dev->control->event_types[i].data) 2467 continue; 2468 2469 if (!(mask & dev->control->event_types[i].mask)) 2470 continue; 2471 2472 for (j = 0; dev->control->event_types[i].events[j].event; j++) { 2473 if (ev == dev->control->event_types[i].events[j].data) { 2474 device_event = 2475 dev->control-> 2476 event_types[i].events[j].event; 2477 goto found; 2478 } 2479 } 2480 } 2481 /* Still not able to decode the event try to pass 2482 * it over to the minidriver 2483 */ 2484 if (dev->control->handle_irq && 2485 dev->control->handle_irq(data_mask, ev) == 0) 2486 return IRQ_HANDLED; 2487 2488 dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2489 ev, data_mask, dev->cur_ioport->io1.minimum, 2490 dev->control->evport_offset); 2491 return IRQ_HANDLED; 2492 2493 found: 2494 sony_laptop_report_input_event(device_event); 2495 acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); 2496 sonypi_compat_report_event(device_event); 2497 2498 return IRQ_HANDLED; 2499 } 2500 2501 /***************** 2502 * 2503 * ACPI driver 2504 * 2505 *****************/ 2506 static int sony_pic_remove(struct acpi_device *device, int type) 2507 { 2508 struct sony_pic_ioport *io, *tmp_io; 2509 struct sony_pic_irq *irq, *tmp_irq; 2510 2511 if (sony_pic_disable(device)) { 2512 printk(KERN_ERR DRV_PFX "Couldn't disable device.\n"); 2513 return -ENXIO; 2514 } 2515 2516 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2517 release_region(spic_dev.cur_ioport->io1.minimum, 2518 spic_dev.cur_ioport->io1.address_length); 2519 if (spic_dev.cur_ioport->io2.minimum) 2520 release_region(spic_dev.cur_ioport->io2.minimum, 2521 spic_dev.cur_ioport->io2.address_length); 2522 2523 sonypi_compat_exit(); 2524 2525 sony_laptop_remove_input(); 2526 2527 /* pf attrs */ 2528 sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group); 2529 sony_pf_remove(); 2530 2531 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) { 2532 list_del(&io->list); 2533 kfree(io); 2534 } 2535 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) { 2536 list_del(&irq->list); 2537 kfree(irq); 2538 } 2539 spic_dev.cur_ioport = NULL; 2540 spic_dev.cur_irq = NULL; 2541 2542 dprintk(SONY_PIC_DRIVER_NAME " removed.\n"); 2543 return 0; 2544 } 2545 2546 static int sony_pic_add(struct acpi_device *device) 2547 { 2548 int result; 2549 struct sony_pic_ioport *io, *tmp_io; 2550 struct sony_pic_irq *irq, *tmp_irq; 2551 2552 printk(KERN_INFO DRV_PFX "%s v%s.\n", 2553 SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); 2554 2555 spic_dev.acpi_dev = device; 2556 strcpy(acpi_device_class(device), "sony/hotkey"); 2557 sony_pic_detect_device_type(&spic_dev); 2558 mutex_init(&spic_dev.lock); 2559 2560 /* read _PRS resources */ 2561 result = sony_pic_possible_resources(device); 2562 if (result) { 2563 printk(KERN_ERR DRV_PFX 2564 "Unabe to read possible resources.\n"); 2565 goto err_free_resources; 2566 } 2567 2568 /* setup input devices and helper fifo */ 2569 result = sony_laptop_setup_input(device); 2570 if (result) { 2571 printk(KERN_ERR DRV_PFX 2572 "Unabe to create input devices.\n"); 2573 goto err_free_resources; 2574 } 2575 2576 if (sonypi_compat_init()) 2577 goto err_remove_input; 2578 2579 /* request io port */ 2580 list_for_each_entry_reverse(io, &spic_dev.ioports, list) { 2581 if (request_region(io->io1.minimum, io->io1.address_length, 2582 "Sony Programable I/O Device")) { 2583 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n", 2584 io->io1.minimum, io->io1.maximum, 2585 io->io1.address_length); 2586 /* Type 1 have 2 ioports */ 2587 if (io->io2.minimum) { 2588 if (request_region(io->io2.minimum, 2589 io->io2.address_length, 2590 "Sony Programable I/O Device")) { 2591 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n", 2592 io->io2.minimum, io->io2.maximum, 2593 io->io2.address_length); 2594 spic_dev.cur_ioport = io; 2595 break; 2596 } 2597 else { 2598 dprintk("Unable to get I/O port2: " 2599 "0x%.4x (0x%.4x) + 0x%.2x\n", 2600 io->io2.minimum, io->io2.maximum, 2601 io->io2.address_length); 2602 release_region(io->io1.minimum, 2603 io->io1.address_length); 2604 } 2605 } 2606 else { 2607 spic_dev.cur_ioport = io; 2608 break; 2609 } 2610 } 2611 } 2612 if (!spic_dev.cur_ioport) { 2613 printk(KERN_ERR DRV_PFX "Failed to request_region.\n"); 2614 result = -ENODEV; 2615 goto err_remove_compat; 2616 } 2617 2618 /* request IRQ */ 2619 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) { 2620 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, 2621 IRQF_SHARED, "sony-laptop", &spic_dev)) { 2622 dprintk("IRQ: %d - triggering: %d - " 2623 "polarity: %d - shr: %d\n", 2624 irq->irq.interrupts[0], 2625 irq->irq.triggering, 2626 irq->irq.polarity, 2627 irq->irq.sharable); 2628 spic_dev.cur_irq = irq; 2629 break; 2630 } 2631 } 2632 if (!spic_dev.cur_irq) { 2633 printk(KERN_ERR DRV_PFX "Failed to request_irq.\n"); 2634 result = -ENODEV; 2635 goto err_release_region; 2636 } 2637 2638 /* set resource status _SRS */ 2639 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq); 2640 if (result) { 2641 printk(KERN_ERR DRV_PFX "Couldn't enable device.\n"); 2642 goto err_free_irq; 2643 } 2644 2645 spic_dev.bluetooth_power = -1; 2646 /* create device attributes */ 2647 result = sony_pf_add(); 2648 if (result) 2649 goto err_disable_device; 2650 2651 result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group); 2652 if (result) 2653 goto err_remove_pf; 2654 2655 return 0; 2656 2657 err_remove_pf: 2658 sony_pf_remove(); 2659 2660 err_disable_device: 2661 sony_pic_disable(device); 2662 2663 err_free_irq: 2664 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2665 2666 err_release_region: 2667 release_region(spic_dev.cur_ioport->io1.minimum, 2668 spic_dev.cur_ioport->io1.address_length); 2669 if (spic_dev.cur_ioport->io2.minimum) 2670 release_region(spic_dev.cur_ioport->io2.minimum, 2671 spic_dev.cur_ioport->io2.address_length); 2672 2673 err_remove_compat: 2674 sonypi_compat_exit(); 2675 2676 err_remove_input: 2677 sony_laptop_remove_input(); 2678 2679 err_free_resources: 2680 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) { 2681 list_del(&io->list); 2682 kfree(io); 2683 } 2684 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) { 2685 list_del(&irq->list); 2686 kfree(irq); 2687 } 2688 spic_dev.cur_ioport = NULL; 2689 spic_dev.cur_irq = NULL; 2690 2691 return result; 2692 } 2693 2694 static int sony_pic_suspend(struct acpi_device *device, pm_message_t state) 2695 { 2696 if (sony_pic_disable(device)) 2697 return -ENXIO; 2698 return 0; 2699 } 2700 2701 static int sony_pic_resume(struct acpi_device *device) 2702 { 2703 sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq); 2704 return 0; 2705 } 2706 2707 static const struct acpi_device_id sony_pic_device_ids[] = { 2708 {SONY_PIC_HID, 0}, 2709 {"", 0}, 2710 }; 2711 2712 static struct acpi_driver sony_pic_driver = { 2713 .name = SONY_PIC_DRIVER_NAME, 2714 .class = SONY_PIC_CLASS, 2715 .ids = sony_pic_device_ids, 2716 .owner = THIS_MODULE, 2717 .ops = { 2718 .add = sony_pic_add, 2719 .remove = sony_pic_remove, 2720 .suspend = sony_pic_suspend, 2721 .resume = sony_pic_resume, 2722 }, 2723 }; 2724 2725 static struct dmi_system_id __initdata sonypi_dmi_table[] = { 2726 { 2727 .ident = "Sony Vaio", 2728 .matches = { 2729 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 2730 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"), 2731 }, 2732 }, 2733 { 2734 .ident = "Sony Vaio", 2735 .matches = { 2736 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 2737 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"), 2738 }, 2739 }, 2740 { } 2741 }; 2742 2743 static int __init sony_laptop_init(void) 2744 { 2745 int result; 2746 2747 if (!no_spic && dmi_check_system(sonypi_dmi_table)) { 2748 result = acpi_bus_register_driver(&sony_pic_driver); 2749 if (result) { 2750 printk(KERN_ERR DRV_PFX 2751 "Unable to register SPIC driver."); 2752 goto out; 2753 } 2754 } 2755 2756 result = acpi_bus_register_driver(&sony_nc_driver); 2757 if (result) { 2758 printk(KERN_ERR DRV_PFX "Unable to register SNC driver."); 2759 goto out_unregister_pic; 2760 } 2761 2762 return 0; 2763 2764 out_unregister_pic: 2765 if (!no_spic) 2766 acpi_bus_unregister_driver(&sony_pic_driver); 2767 out: 2768 return result; 2769 } 2770 2771 static void __exit sony_laptop_exit(void) 2772 { 2773 acpi_bus_unregister_driver(&sony_nc_driver); 2774 if (!no_spic) 2775 acpi_bus_unregister_driver(&sony_pic_driver); 2776 } 2777 2778 module_init(sony_laptop_init); 2779 module_exit(sony_laptop_exit); 2780