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-2009 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 46 47 #include <linux/kernel.h> 48 #include <linux/module.h> 49 #include <linux/moduleparam.h> 50 #include <linux/init.h> 51 #include <linux/types.h> 52 #include <linux/backlight.h> 53 #include <linux/platform_device.h> 54 #include <linux/err.h> 55 #include <linux/dmi.h> 56 #include <linux/pci.h> 57 #include <linux/interrupt.h> 58 #include <linux/delay.h> 59 #include <linux/input.h> 60 #include <linux/kfifo.h> 61 #include <linux/workqueue.h> 62 #include <linux/acpi.h> 63 #include <linux/slab.h> 64 #include <acpi/acpi_drivers.h> 65 #include <acpi/acpi_bus.h> 66 #include <asm/uaccess.h> 67 #include <linux/sonypi.h> 68 #include <linux/sony-laptop.h> 69 #include <linux/rfkill.h> 70 #ifdef CONFIG_SONYPI_COMPAT 71 #include <linux/poll.h> 72 #include <linux/miscdevice.h> 73 #endif 74 75 #define dprintk(fmt, ...) \ 76 do { \ 77 if (debug) \ 78 pr_warn(fmt, ##__VA_ARGS__); \ 79 } while (0) 80 81 #define SONY_LAPTOP_DRIVER_VERSION "0.6" 82 83 #define SONY_NC_CLASS "sony-nc" 84 #define SONY_NC_HID "SNY5001" 85 #define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver" 86 87 #define SONY_PIC_CLASS "sony-pic" 88 #define SONY_PIC_HID "SNY6001" 89 #define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver" 90 91 MODULE_AUTHOR("Stelian Pop, Mattia Dongili"); 92 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)"); 93 MODULE_LICENSE("GPL"); 94 MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION); 95 96 static int debug; 97 module_param(debug, int, 0); 98 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " 99 "the development of this driver"); 100 101 static int no_spic; /* = 0 */ 102 module_param(no_spic, int, 0444); 103 MODULE_PARM_DESC(no_spic, 104 "set this if you don't want to enable the SPIC device"); 105 106 static int compat; /* = 0 */ 107 module_param(compat, int, 0444); 108 MODULE_PARM_DESC(compat, 109 "set this if you want to enable backward compatibility mode"); 110 111 static unsigned long mask = 0xffffffff; 112 module_param(mask, ulong, 0644); 113 MODULE_PARM_DESC(mask, 114 "set this to the mask of event you want to enable (see doc)"); 115 116 static int camera; /* = 0 */ 117 module_param(camera, int, 0444); 118 MODULE_PARM_DESC(camera, 119 "set this to 1 to enable Motion Eye camera controls " 120 "(only use it if you have a C1VE or C1VN model)"); 121 122 #ifdef CONFIG_SONYPI_COMPAT 123 static int minor = -1; 124 module_param(minor, int, 0); 125 MODULE_PARM_DESC(minor, 126 "minor number of the misc device for the SPIC compatibility code, " 127 "default is -1 (automatic)"); 128 #endif 129 130 static int kbd_backlight = 1; 131 module_param(kbd_backlight, int, 0444); 132 MODULE_PARM_DESC(kbd_backlight, 133 "set this to 0 to disable keyboard backlight, " 134 "1 to enable it (default: 0)"); 135 136 static int kbd_backlight_timeout; /* = 0 */ 137 module_param(kbd_backlight_timeout, int, 0444); 138 MODULE_PARM_DESC(kbd_backlight_timeout, 139 "set this to 0 to set the default 10 seconds timeout, " 140 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " 141 "(default: 0)"); 142 143 #ifdef CONFIG_PM_SLEEP 144 static void sony_nc_kbd_backlight_resume(void); 145 static void sony_nc_thermal_resume(void); 146 #endif 147 static int sony_nc_kbd_backlight_setup(struct platform_device *pd, 148 unsigned int handle); 149 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); 150 151 static int sony_nc_battery_care_setup(struct platform_device *pd, 152 unsigned int handle); 153 static void sony_nc_battery_care_cleanup(struct platform_device *pd); 154 155 static int sony_nc_thermal_setup(struct platform_device *pd); 156 static void sony_nc_thermal_cleanup(struct platform_device *pd); 157 158 static int sony_nc_lid_resume_setup(struct platform_device *pd); 159 static void sony_nc_lid_resume_cleanup(struct platform_device *pd); 160 161 static int sony_nc_highspeed_charging_setup(struct platform_device *pd); 162 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); 163 164 static int sony_nc_touchpad_setup(struct platform_device *pd, 165 unsigned int handle); 166 static void sony_nc_touchpad_cleanup(struct platform_device *pd); 167 168 enum sony_nc_rfkill { 169 SONY_WIFI, 170 SONY_BLUETOOTH, 171 SONY_WWAN, 172 SONY_WIMAX, 173 N_SONY_RFKILL, 174 }; 175 176 static int sony_rfkill_handle; 177 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; 178 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; 179 static int sony_nc_rfkill_setup(struct acpi_device *device, 180 unsigned int handle); 181 static void sony_nc_rfkill_cleanup(void); 182 static void sony_nc_rfkill_update(void); 183 184 /*********** Input Devices ***********/ 185 186 #define SONY_LAPTOP_BUF_SIZE 128 187 struct sony_laptop_input_s { 188 atomic_t users; 189 struct input_dev *jog_dev; 190 struct input_dev *key_dev; 191 struct kfifo fifo; 192 spinlock_t fifo_lock; 193 struct timer_list release_key_timer; 194 }; 195 196 static struct sony_laptop_input_s sony_laptop_input = { 197 .users = ATOMIC_INIT(0), 198 }; 199 200 struct sony_laptop_keypress { 201 struct input_dev *dev; 202 int key; 203 }; 204 205 /* Correspondance table between sonypi events 206 * and input layer indexes in the keymap 207 */ 208 static int sony_laptop_input_index[] = { 209 -1, /* 0 no event */ 210 -1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */ 211 -1, /* 2 SONYPI_EVENT_JOGDIAL_UP */ 212 -1, /* 3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ 213 -1, /* 4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */ 214 -1, /* 5 SONYPI_EVENT_JOGDIAL_PRESSED */ 215 -1, /* 6 SONYPI_EVENT_JOGDIAL_RELEASED */ 216 0, /* 7 SONYPI_EVENT_CAPTURE_PRESSED */ 217 1, /* 8 SONYPI_EVENT_CAPTURE_RELEASED */ 218 2, /* 9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 219 3, /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 220 4, /* 11 SONYPI_EVENT_FNKEY_ESC */ 221 5, /* 12 SONYPI_EVENT_FNKEY_F1 */ 222 6, /* 13 SONYPI_EVENT_FNKEY_F2 */ 223 7, /* 14 SONYPI_EVENT_FNKEY_F3 */ 224 8, /* 15 SONYPI_EVENT_FNKEY_F4 */ 225 9, /* 16 SONYPI_EVENT_FNKEY_F5 */ 226 10, /* 17 SONYPI_EVENT_FNKEY_F6 */ 227 11, /* 18 SONYPI_EVENT_FNKEY_F7 */ 228 12, /* 19 SONYPI_EVENT_FNKEY_F8 */ 229 13, /* 20 SONYPI_EVENT_FNKEY_F9 */ 230 14, /* 21 SONYPI_EVENT_FNKEY_F10 */ 231 15, /* 22 SONYPI_EVENT_FNKEY_F11 */ 232 16, /* 23 SONYPI_EVENT_FNKEY_F12 */ 233 17, /* 24 SONYPI_EVENT_FNKEY_1 */ 234 18, /* 25 SONYPI_EVENT_FNKEY_2 */ 235 19, /* 26 SONYPI_EVENT_FNKEY_D */ 236 20, /* 27 SONYPI_EVENT_FNKEY_E */ 237 21, /* 28 SONYPI_EVENT_FNKEY_F */ 238 22, /* 29 SONYPI_EVENT_FNKEY_S */ 239 23, /* 30 SONYPI_EVENT_FNKEY_B */ 240 24, /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */ 241 25, /* 32 SONYPI_EVENT_PKEY_P1 */ 242 26, /* 33 SONYPI_EVENT_PKEY_P2 */ 243 27, /* 34 SONYPI_EVENT_PKEY_P3 */ 244 28, /* 35 SONYPI_EVENT_BACK_PRESSED */ 245 -1, /* 36 SONYPI_EVENT_LID_CLOSED */ 246 -1, /* 37 SONYPI_EVENT_LID_OPENED */ 247 29, /* 38 SONYPI_EVENT_BLUETOOTH_ON */ 248 30, /* 39 SONYPI_EVENT_BLUETOOTH_OFF */ 249 31, /* 40 SONYPI_EVENT_HELP_PRESSED */ 250 32, /* 41 SONYPI_EVENT_FNKEY_ONLY */ 251 33, /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 252 34, /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */ 253 35, /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 254 36, /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 255 37, /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 256 38, /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 257 39, /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 258 40, /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 259 41, /* 50 SONYPI_EVENT_ZOOM_PRESSED */ 260 42, /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 261 43, /* 52 SONYPI_EVENT_MEYE_FACE */ 262 44, /* 53 SONYPI_EVENT_MEYE_OPPOSITE */ 263 45, /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */ 264 46, /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */ 265 -1, /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */ 266 -1, /* 57 SONYPI_EVENT_BATTERY_INSERT */ 267 -1, /* 58 SONYPI_EVENT_BATTERY_REMOVE */ 268 -1, /* 59 SONYPI_EVENT_FNKEY_RELEASED */ 269 47, /* 60 SONYPI_EVENT_WIRELESS_ON */ 270 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 271 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 272 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 273 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ 274 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */ 275 53, /* 66 SONYPI_EVENT_PKEY_P4 */ 276 54, /* 67 SONYPI_EVENT_PKEY_P5 */ 277 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ 278 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 279 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 280 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ 281 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ 282 59, /* 72 SONYPI_EVENT_VENDOR_PRESSED */ 283 }; 284 285 static int sony_laptop_input_keycode_map[] = { 286 KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */ 287 KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */ 288 KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 289 KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 290 KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */ 291 KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */ 292 KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */ 293 KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */ 294 KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */ 295 KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */ 296 KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */ 297 KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */ 298 KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */ 299 KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */ 300 KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ 301 KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ 302 KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ 303 KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ 304 KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ 305 KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ 306 KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ 307 KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ 308 KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */ 309 KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */ 310 KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */ 311 KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */ 312 KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */ 313 KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */ 314 KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */ 315 KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */ 316 KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */ 317 KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */ 318 KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */ 319 KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 320 KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */ 321 KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 322 KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 323 KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 324 KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 325 KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 326 KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 327 KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */ 328 BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 329 KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */ 330 KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */ 331 KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */ 332 KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ 333 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ 334 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ 335 KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ 336 KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 337 KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ 338 KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */ 339 KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ 340 KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ 341 KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ 342 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ 343 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 344 KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ 345 KEY_VENDOR, /* 59 SONYPI_EVENT_VENDOR_PRESSED */ 346 }; 347 348 /* release buttons after a short delay if pressed */ 349 static void do_sony_laptop_release_key(unsigned long unused) 350 { 351 struct sony_laptop_keypress kp; 352 unsigned long flags; 353 354 spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags); 355 356 if (kfifo_out(&sony_laptop_input.fifo, 357 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { 358 input_report_key(kp.dev, kp.key, 0); 359 input_sync(kp.dev); 360 } 361 362 /* If there is something in the fifo schedule next release. */ 363 if (kfifo_len(&sony_laptop_input.fifo) != 0) 364 mod_timer(&sony_laptop_input.release_key_timer, 365 jiffies + msecs_to_jiffies(10)); 366 367 spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); 368 } 369 370 /* forward event to the input subsystem */ 371 static void sony_laptop_report_input_event(u8 event) 372 { 373 struct input_dev *jog_dev = sony_laptop_input.jog_dev; 374 struct input_dev *key_dev = sony_laptop_input.key_dev; 375 struct sony_laptop_keypress kp = { NULL }; 376 int scancode = -1; 377 378 if (event == SONYPI_EVENT_FNKEY_RELEASED || 379 event == SONYPI_EVENT_ANYBUTTON_RELEASED) { 380 /* Nothing, not all VAIOs generate this event */ 381 return; 382 } 383 384 /* report events */ 385 switch (event) { 386 /* jog_dev events */ 387 case SONYPI_EVENT_JOGDIAL_UP: 388 case SONYPI_EVENT_JOGDIAL_UP_PRESSED: 389 input_report_rel(jog_dev, REL_WHEEL, 1); 390 input_sync(jog_dev); 391 return; 392 393 case SONYPI_EVENT_JOGDIAL_DOWN: 394 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: 395 input_report_rel(jog_dev, REL_WHEEL, -1); 396 input_sync(jog_dev); 397 return; 398 399 /* key_dev events */ 400 case SONYPI_EVENT_JOGDIAL_PRESSED: 401 kp.key = BTN_MIDDLE; 402 kp.dev = jog_dev; 403 break; 404 405 default: 406 if (event >= ARRAY_SIZE(sony_laptop_input_index)) { 407 dprintk("sony_laptop_report_input_event, event not known: %d\n", event); 408 break; 409 } 410 if ((scancode = sony_laptop_input_index[event]) != -1) { 411 kp.key = sony_laptop_input_keycode_map[scancode]; 412 if (kp.key != KEY_UNKNOWN) 413 kp.dev = key_dev; 414 } 415 break; 416 } 417 418 if (kp.dev) { 419 /* if we have a scancode we emit it so we can always 420 remap the key */ 421 if (scancode != -1) 422 input_event(kp.dev, EV_MSC, MSC_SCAN, scancode); 423 input_report_key(kp.dev, kp.key, 1); 424 input_sync(kp.dev); 425 426 /* schedule key release */ 427 kfifo_in_locked(&sony_laptop_input.fifo, 428 (unsigned char *)&kp, sizeof(kp), 429 &sony_laptop_input.fifo_lock); 430 mod_timer(&sony_laptop_input.release_key_timer, 431 jiffies + msecs_to_jiffies(10)); 432 } else 433 dprintk("unknown input event %.2x\n", event); 434 } 435 436 static int sony_laptop_setup_input(struct acpi_device *acpi_device) 437 { 438 struct input_dev *jog_dev; 439 struct input_dev *key_dev; 440 int i; 441 int error; 442 443 /* don't run again if already initialized */ 444 if (atomic_add_return(1, &sony_laptop_input.users) > 1) 445 return 0; 446 447 /* kfifo */ 448 spin_lock_init(&sony_laptop_input.fifo_lock); 449 error = kfifo_alloc(&sony_laptop_input.fifo, 450 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 451 if (error) { 452 pr_err("kfifo_alloc failed\n"); 453 goto err_dec_users; 454 } 455 456 setup_timer(&sony_laptop_input.release_key_timer, 457 do_sony_laptop_release_key, 0); 458 459 /* input keys */ 460 key_dev = input_allocate_device(); 461 if (!key_dev) { 462 error = -ENOMEM; 463 goto err_free_kfifo; 464 } 465 466 key_dev->name = "Sony Vaio Keys"; 467 key_dev->id.bustype = BUS_ISA; 468 key_dev->id.vendor = PCI_VENDOR_ID_SONY; 469 key_dev->dev.parent = &acpi_device->dev; 470 471 /* Initialize the Input Drivers: special keys */ 472 input_set_capability(key_dev, EV_MSC, MSC_SCAN); 473 474 __set_bit(EV_KEY, key_dev->evbit); 475 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 476 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 477 key_dev->keycode = &sony_laptop_input_keycode_map; 478 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) 479 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit); 480 __clear_bit(KEY_RESERVED, key_dev->keybit); 481 482 error = input_register_device(key_dev); 483 if (error) 484 goto err_free_keydev; 485 486 sony_laptop_input.key_dev = key_dev; 487 488 /* jogdial */ 489 jog_dev = input_allocate_device(); 490 if (!jog_dev) { 491 error = -ENOMEM; 492 goto err_unregister_keydev; 493 } 494 495 jog_dev->name = "Sony Vaio Jogdial"; 496 jog_dev->id.bustype = BUS_ISA; 497 jog_dev->id.vendor = PCI_VENDOR_ID_SONY; 498 jog_dev->dev.parent = &acpi_device->dev; 499 500 input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE); 501 input_set_capability(jog_dev, EV_REL, REL_WHEEL); 502 503 error = input_register_device(jog_dev); 504 if (error) 505 goto err_free_jogdev; 506 507 sony_laptop_input.jog_dev = jog_dev; 508 509 return 0; 510 511 err_free_jogdev: 512 input_free_device(jog_dev); 513 514 err_unregister_keydev: 515 input_unregister_device(key_dev); 516 /* to avoid kref underflow below at input_free_device */ 517 key_dev = NULL; 518 519 err_free_keydev: 520 input_free_device(key_dev); 521 522 err_free_kfifo: 523 kfifo_free(&sony_laptop_input.fifo); 524 525 err_dec_users: 526 atomic_dec(&sony_laptop_input.users); 527 return error; 528 } 529 530 static void sony_laptop_remove_input(void) 531 { 532 struct sony_laptop_keypress kp = { NULL }; 533 534 /* Cleanup only after the last user has gone */ 535 if (!atomic_dec_and_test(&sony_laptop_input.users)) 536 return; 537 538 del_timer_sync(&sony_laptop_input.release_key_timer); 539 540 /* 541 * Generate key-up events for remaining keys. Note that we don't 542 * need locking since nobody is adding new events to the kfifo. 543 */ 544 while (kfifo_out(&sony_laptop_input.fifo, 545 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { 546 input_report_key(kp.dev, kp.key, 0); 547 input_sync(kp.dev); 548 } 549 550 /* destroy input devs */ 551 input_unregister_device(sony_laptop_input.key_dev); 552 sony_laptop_input.key_dev = NULL; 553 554 if (sony_laptop_input.jog_dev) { 555 input_unregister_device(sony_laptop_input.jog_dev); 556 sony_laptop_input.jog_dev = NULL; 557 } 558 559 kfifo_free(&sony_laptop_input.fifo); 560 } 561 562 /*********** Platform Device ***********/ 563 564 static atomic_t sony_pf_users = ATOMIC_INIT(0); 565 static struct platform_driver sony_pf_driver = { 566 .driver = { 567 .name = "sony-laptop", 568 .owner = THIS_MODULE, 569 } 570 }; 571 static struct platform_device *sony_pf_device; 572 573 static int sony_pf_add(void) 574 { 575 int ret = 0; 576 577 /* don't run again if already initialized */ 578 if (atomic_add_return(1, &sony_pf_users) > 1) 579 return 0; 580 581 ret = platform_driver_register(&sony_pf_driver); 582 if (ret) 583 goto out; 584 585 sony_pf_device = platform_device_alloc("sony-laptop", -1); 586 if (!sony_pf_device) { 587 ret = -ENOMEM; 588 goto out_platform_registered; 589 } 590 591 ret = platform_device_add(sony_pf_device); 592 if (ret) 593 goto out_platform_alloced; 594 595 return 0; 596 597 out_platform_alloced: 598 platform_device_put(sony_pf_device); 599 sony_pf_device = NULL; 600 out_platform_registered: 601 platform_driver_unregister(&sony_pf_driver); 602 out: 603 atomic_dec(&sony_pf_users); 604 return ret; 605 } 606 607 static void sony_pf_remove(void) 608 { 609 /* deregister only after the last user has gone */ 610 if (!atomic_dec_and_test(&sony_pf_users)) 611 return; 612 613 platform_device_unregister(sony_pf_device); 614 platform_driver_unregister(&sony_pf_driver); 615 } 616 617 /*********** SNC (SNY5001) Device ***********/ 618 619 /* the device uses 1-based values, while the backlight subsystem uses 620 0-based values */ 621 #define SONY_MAX_BRIGHTNESS 8 622 623 #define SNC_VALIDATE_IN 0 624 #define SNC_VALIDATE_OUT 1 625 626 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *, 627 char *); 628 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *, 629 const char *, size_t); 630 static int boolean_validate(const int, const int); 631 static int brightness_default_validate(const int, const int); 632 633 struct sony_nc_value { 634 char *name; /* name of the entry */ 635 char **acpiget; /* names of the ACPI get function */ 636 char **acpiset; /* names of the ACPI set function */ 637 int (*validate)(const int, const int); /* input/output validation */ 638 int value; /* current setting */ 639 int valid; /* Has ever been set */ 640 int debug; /* active only in debug mode ? */ 641 struct device_attribute devattr; /* sysfs attribute */ 642 }; 643 644 #define SNC_HANDLE_NAMES(_name, _values...) \ 645 static char *snc_##_name[] = { _values, NULL } 646 647 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \ 648 { \ 649 .name = __stringify(_name), \ 650 .acpiget = _getters, \ 651 .acpiset = _setters, \ 652 .validate = _validate, \ 653 .debug = _debug, \ 654 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \ 655 } 656 657 #define SNC_HANDLE_NULL { .name = NULL } 658 659 SNC_HANDLE_NAMES(fnkey_get, "GHKE"); 660 661 SNC_HANDLE_NAMES(brightness_def_get, "GPBR"); 662 SNC_HANDLE_NAMES(brightness_def_set, "SPBR"); 663 664 SNC_HANDLE_NAMES(cdpower_get, "GCDP"); 665 SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW"); 666 667 SNC_HANDLE_NAMES(audiopower_get, "GAZP"); 668 SNC_HANDLE_NAMES(audiopower_set, "AZPW"); 669 670 SNC_HANDLE_NAMES(lanpower_get, "GLNP"); 671 SNC_HANDLE_NAMES(lanpower_set, "LNPW"); 672 673 SNC_HANDLE_NAMES(lidstate_get, "GLID"); 674 675 SNC_HANDLE_NAMES(indicatorlamp_get, "GILS"); 676 SNC_HANDLE_NAMES(indicatorlamp_set, "SILS"); 677 678 SNC_HANDLE_NAMES(gainbass_get, "GMGB"); 679 SNC_HANDLE_NAMES(gainbass_set, "CMGB"); 680 681 SNC_HANDLE_NAMES(PID_get, "GPID"); 682 683 SNC_HANDLE_NAMES(CTR_get, "GCTR"); 684 SNC_HANDLE_NAMES(CTR_set, "SCTR"); 685 686 SNC_HANDLE_NAMES(PCR_get, "GPCR"); 687 SNC_HANDLE_NAMES(PCR_set, "SPCR"); 688 689 SNC_HANDLE_NAMES(CMI_get, "GCMI"); 690 SNC_HANDLE_NAMES(CMI_set, "SCMI"); 691 692 static struct sony_nc_value sony_nc_values[] = { 693 SNC_HANDLE(brightness_default, snc_brightness_def_get, 694 snc_brightness_def_set, brightness_default_validate, 0), 695 SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0), 696 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0), 697 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set, 698 boolean_validate, 0), 699 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, 700 boolean_validate, 1), 701 SNC_HANDLE(lidstate, snc_lidstate_get, NULL, 702 boolean_validate, 0), 703 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set, 704 boolean_validate, 0), 705 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set, 706 boolean_validate, 0), 707 /* unknown methods */ 708 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), 709 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), 710 SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1), 711 SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1), 712 SNC_HANDLE_NULL 713 }; 714 715 static acpi_handle sony_nc_acpi_handle; 716 static struct acpi_device *sony_nc_acpi_device = NULL; 717 718 /* 719 * acpi_evaluate_object wrappers 720 * all useful calls into SNC methods take one or zero parameters and return 721 * integers or arrays. 722 */ 723 static union acpi_object *__call_snc_method(acpi_handle handle, char *method, 724 u64 *value) 725 { 726 union acpi_object *result = NULL; 727 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 728 acpi_status status; 729 730 if (value) { 731 struct acpi_object_list params; 732 union acpi_object in; 733 in.type = ACPI_TYPE_INTEGER; 734 in.integer.value = *value; 735 params.count = 1; 736 params.pointer = ∈ 737 status = acpi_evaluate_object(handle, method, ¶ms, &output); 738 dprintk("__call_snc_method: [%s:0x%.8x%.8x]\n", method, 739 (unsigned int)(*value >> 32), 740 (unsigned int)*value & 0xffffffff); 741 } else { 742 status = acpi_evaluate_object(handle, method, NULL, &output); 743 dprintk("__call_snc_method: [%s]\n", method); 744 } 745 746 if (ACPI_FAILURE(status)) { 747 pr_err("Failed to evaluate [%s]\n", method); 748 return NULL; 749 } 750 751 result = (union acpi_object *) output.pointer; 752 if (!result) 753 dprintk("No return object [%s]\n", method); 754 755 return result; 756 } 757 758 static int sony_nc_int_call(acpi_handle handle, char *name, int *value, 759 int *result) 760 { 761 union acpi_object *object = NULL; 762 if (value) { 763 u64 v = *value; 764 object = __call_snc_method(handle, name, &v); 765 } else 766 object = __call_snc_method(handle, name, NULL); 767 768 if (!object) 769 return -EINVAL; 770 771 if (object->type != ACPI_TYPE_INTEGER) { 772 pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", 773 ACPI_TYPE_INTEGER, object->type); 774 kfree(object); 775 return -EINVAL; 776 } 777 778 if (result) 779 *result = object->integer.value; 780 781 kfree(object); 782 return 0; 783 } 784 785 #define MIN(a, b) (a > b ? b : a) 786 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, 787 void *buffer, size_t buflen) 788 { 789 int ret = 0; 790 size_t len = len; 791 union acpi_object *object = __call_snc_method(handle, name, value); 792 793 if (!object) 794 return -EINVAL; 795 796 if (object->type == ACPI_TYPE_BUFFER) { 797 len = MIN(buflen, object->buffer.length); 798 memcpy(buffer, object->buffer.pointer, len); 799 800 } else if (object->type == ACPI_TYPE_INTEGER) { 801 len = MIN(buflen, sizeof(object->integer.value)); 802 memcpy(buffer, &object->integer.value, len); 803 804 } else { 805 pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", 806 ACPI_TYPE_BUFFER, object->type); 807 ret = -EINVAL; 808 } 809 810 kfree(object); 811 return ret; 812 } 813 814 struct sony_nc_handles { 815 u16 cap[0x10]; 816 struct device_attribute devattr; 817 }; 818 819 static struct sony_nc_handles *handles; 820 821 static ssize_t sony_nc_handles_show(struct device *dev, 822 struct device_attribute *attr, char *buffer) 823 { 824 ssize_t len = 0; 825 int i; 826 827 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { 828 len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", 829 handles->cap[i]); 830 } 831 len += snprintf(buffer + len, PAGE_SIZE - len, "\n"); 832 833 return len; 834 } 835 836 static int sony_nc_handles_setup(struct platform_device *pd) 837 { 838 int i, r, result, arg; 839 840 handles = kzalloc(sizeof(*handles), GFP_KERNEL); 841 if (!handles) 842 return -ENOMEM; 843 844 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { 845 arg = i + 0x20; 846 r = sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, 847 &result); 848 if (!r) { 849 dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n", 850 result, i); 851 handles->cap[i] = result; 852 } 853 } 854 855 if (debug) { 856 sysfs_attr_init(&handles->devattr.attr); 857 handles->devattr.attr.name = "handles"; 858 handles->devattr.attr.mode = S_IRUGO; 859 handles->devattr.show = sony_nc_handles_show; 860 861 /* allow reading capabilities via sysfs */ 862 if (device_create_file(&pd->dev, &handles->devattr)) { 863 kfree(handles); 864 handles = NULL; 865 return -1; 866 } 867 } 868 869 return 0; 870 } 871 872 static int sony_nc_handles_cleanup(struct platform_device *pd) 873 { 874 if (handles) { 875 if (debug) 876 device_remove_file(&pd->dev, &handles->devattr); 877 kfree(handles); 878 handles = NULL; 879 } 880 return 0; 881 } 882 883 static int sony_find_snc_handle(int handle) 884 { 885 int i; 886 887 /* not initialized yet, return early */ 888 if (!handles || !handle) 889 return -EINVAL; 890 891 for (i = 0; i < 0x10; i++) { 892 if (handles->cap[i] == handle) { 893 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", 894 handle, i); 895 return i; 896 } 897 } 898 dprintk("handle 0x%.4x not found\n", handle); 899 return -EINVAL; 900 } 901 902 static int sony_call_snc_handle(int handle, int argument, int *result) 903 { 904 int arg, ret = 0; 905 int offset = sony_find_snc_handle(handle); 906 907 if (offset < 0) 908 return offset; 909 910 arg = offset | argument; 911 ret = sony_nc_int_call(sony_nc_acpi_handle, "SN07", &arg, result); 912 dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result); 913 return ret; 914 } 915 916 /* 917 * sony_nc_values input/output validate functions 918 */ 919 920 /* brightness_default_validate: 921 * 922 * manipulate input output values to keep consistency with the 923 * backlight framework for which brightness values are 0-based. 924 */ 925 static int brightness_default_validate(const int direction, const int value) 926 { 927 switch (direction) { 928 case SNC_VALIDATE_OUT: 929 return value - 1; 930 case SNC_VALIDATE_IN: 931 if (value >= 0 && value < SONY_MAX_BRIGHTNESS) 932 return value + 1; 933 } 934 return -EINVAL; 935 } 936 937 /* boolean_validate: 938 * 939 * on input validate boolean values 0/1, on output just pass the 940 * received value. 941 */ 942 static int boolean_validate(const int direction, const int value) 943 { 944 if (direction == SNC_VALIDATE_IN) { 945 if (value != 0 && value != 1) 946 return -EINVAL; 947 } 948 return value; 949 } 950 951 /* 952 * Sysfs show/store common to all sony_nc_values 953 */ 954 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr, 955 char *buffer) 956 { 957 int value, ret = 0; 958 struct sony_nc_value *item = 959 container_of(attr, struct sony_nc_value, devattr); 960 961 if (!*item->acpiget) 962 return -EIO; 963 964 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiget, NULL, 965 &value); 966 if (ret < 0) 967 return -EIO; 968 969 if (item->validate) 970 value = item->validate(SNC_VALIDATE_OUT, value); 971 972 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 973 } 974 975 static ssize_t sony_nc_sysfs_store(struct device *dev, 976 struct device_attribute *attr, 977 const char *buffer, size_t count) 978 { 979 int value; 980 int ret = 0; 981 struct sony_nc_value *item = 982 container_of(attr, struct sony_nc_value, devattr); 983 984 if (!item->acpiset) 985 return -EIO; 986 987 if (count > 31) 988 return -EINVAL; 989 990 if (kstrtoint(buffer, 10, &value)) 991 return -EINVAL; 992 993 if (item->validate) 994 value = item->validate(SNC_VALIDATE_IN, value); 995 996 if (value < 0) 997 return value; 998 999 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, 1000 &value, NULL); 1001 if (ret < 0) 1002 return -EIO; 1003 1004 item->value = value; 1005 item->valid = 1; 1006 return count; 1007 } 1008 1009 1010 /* 1011 * Backlight device 1012 */ 1013 struct sony_backlight_props { 1014 struct backlight_device *dev; 1015 int handle; 1016 int cmd_base; 1017 u8 offset; 1018 u8 maxlvl; 1019 }; 1020 struct sony_backlight_props sony_bl_props; 1021 1022 static int sony_backlight_update_status(struct backlight_device *bd) 1023 { 1024 int arg = bd->props.brightness + 1; 1025 return sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &arg, NULL); 1026 } 1027 1028 static int sony_backlight_get_brightness(struct backlight_device *bd) 1029 { 1030 int value; 1031 1032 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, &value)) 1033 return 0; 1034 /* brightness levels are 1-based, while backlight ones are 0-based */ 1035 return value - 1; 1036 } 1037 1038 static int sony_nc_get_brightness_ng(struct backlight_device *bd) 1039 { 1040 int result; 1041 struct sony_backlight_props *sdev = 1042 (struct sony_backlight_props *)bl_get_data(bd); 1043 1044 sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result); 1045 1046 return (result & 0xff) - sdev->offset; 1047 } 1048 1049 static int sony_nc_update_status_ng(struct backlight_device *bd) 1050 { 1051 int value, result; 1052 struct sony_backlight_props *sdev = 1053 (struct sony_backlight_props *)bl_get_data(bd); 1054 1055 value = bd->props.brightness + sdev->offset; 1056 if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10), 1057 &result)) 1058 return -EIO; 1059 1060 return value; 1061 } 1062 1063 static const struct backlight_ops sony_backlight_ops = { 1064 .options = BL_CORE_SUSPENDRESUME, 1065 .update_status = sony_backlight_update_status, 1066 .get_brightness = sony_backlight_get_brightness, 1067 }; 1068 static const struct backlight_ops sony_backlight_ng_ops = { 1069 .options = BL_CORE_SUSPENDRESUME, 1070 .update_status = sony_nc_update_status_ng, 1071 .get_brightness = sony_nc_get_brightness_ng, 1072 }; 1073 1074 /* 1075 * New SNC-only Vaios event mapping to driver known keys 1076 */ 1077 struct sony_nc_event { 1078 u8 data; 1079 u8 event; 1080 }; 1081 1082 static struct sony_nc_event sony_100_events[] = { 1083 { 0x90, SONYPI_EVENT_PKEY_P1 }, 1084 { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1085 { 0x91, SONYPI_EVENT_PKEY_P2 }, 1086 { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1087 { 0x81, SONYPI_EVENT_FNKEY_F1 }, 1088 { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, 1089 { 0x82, SONYPI_EVENT_FNKEY_F2 }, 1090 { 0x02, SONYPI_EVENT_FNKEY_RELEASED }, 1091 { 0x83, SONYPI_EVENT_FNKEY_F3 }, 1092 { 0x03, SONYPI_EVENT_FNKEY_RELEASED }, 1093 { 0x84, SONYPI_EVENT_FNKEY_F4 }, 1094 { 0x04, SONYPI_EVENT_FNKEY_RELEASED }, 1095 { 0x85, SONYPI_EVENT_FNKEY_F5 }, 1096 { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, 1097 { 0x86, SONYPI_EVENT_FNKEY_F6 }, 1098 { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, 1099 { 0x87, SONYPI_EVENT_FNKEY_F7 }, 1100 { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, 1101 { 0x88, SONYPI_EVENT_FNKEY_F8 }, 1102 { 0x08, SONYPI_EVENT_FNKEY_RELEASED }, 1103 { 0x89, SONYPI_EVENT_FNKEY_F9 }, 1104 { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, 1105 { 0x8A, SONYPI_EVENT_FNKEY_F10 }, 1106 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, 1107 { 0x8B, SONYPI_EVENT_FNKEY_F11 }, 1108 { 0x0B, SONYPI_EVENT_FNKEY_RELEASED }, 1109 { 0x8C, SONYPI_EVENT_FNKEY_F12 }, 1110 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 1111 { 0x9d, SONYPI_EVENT_ZOOM_PRESSED }, 1112 { 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1113 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, 1114 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1115 { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, 1116 { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1117 { 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED }, 1118 { 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1119 { 0xa5, SONYPI_EVENT_VENDOR_PRESSED }, 1120 { 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1121 { 0xa6, SONYPI_EVENT_HELP_PRESSED }, 1122 { 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1123 { 0, 0 }, 1124 }; 1125 1126 static struct sony_nc_event sony_127_events[] = { 1127 { 0x81, SONYPI_EVENT_MODEKEY_PRESSED }, 1128 { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1129 { 0x82, SONYPI_EVENT_PKEY_P1 }, 1130 { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1131 { 0x83, SONYPI_EVENT_PKEY_P2 }, 1132 { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1133 { 0x84, SONYPI_EVENT_PKEY_P3 }, 1134 { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1135 { 0x85, SONYPI_EVENT_PKEY_P4 }, 1136 { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1137 { 0x86, SONYPI_EVENT_PKEY_P5 }, 1138 { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1139 { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, 1140 { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, 1141 { 0, 0 }, 1142 }; 1143 1144 static int sony_nc_hotkeys_decode(u32 event, unsigned int handle) 1145 { 1146 int ret = -EINVAL; 1147 unsigned int result = 0; 1148 struct sony_nc_event *key_event; 1149 1150 if (sony_call_snc_handle(handle, 0x200, &result)) { 1151 dprintk("Unable to decode event 0x%.2x 0x%.2x\n", handle, 1152 event); 1153 return -EINVAL; 1154 } 1155 1156 result &= 0xFF; 1157 1158 if (handle == 0x0100) 1159 key_event = sony_100_events; 1160 else 1161 key_event = sony_127_events; 1162 1163 for (; key_event->data; key_event++) { 1164 if (key_event->data == result) { 1165 ret = key_event->event; 1166 break; 1167 } 1168 } 1169 1170 if (!key_event->data) 1171 pr_info("Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n", 1172 event, result, handle); 1173 1174 return ret; 1175 } 1176 1177 /* 1178 * ACPI callbacks 1179 */ 1180 enum event_types { 1181 HOTKEY = 1, 1182 KILLSWITCH, 1183 GFX_SWITCH 1184 }; 1185 static void sony_nc_notify(struct acpi_device *device, u32 event) 1186 { 1187 u32 real_ev = event; 1188 u8 ev_type = 0; 1189 dprintk("sony_nc_notify, event: 0x%.2x\n", event); 1190 1191 if (event >= 0x90) { 1192 unsigned int result = 0; 1193 unsigned int arg = 0; 1194 unsigned int handle = 0; 1195 unsigned int offset = event - 0x90; 1196 1197 if (offset >= ARRAY_SIZE(handles->cap)) { 1198 pr_err("Event 0x%x outside of capabilities list\n", 1199 event); 1200 return; 1201 } 1202 handle = handles->cap[offset]; 1203 1204 /* list of handles known for generating events */ 1205 switch (handle) { 1206 /* hotkey event */ 1207 case 0x0100: 1208 case 0x0127: 1209 ev_type = HOTKEY; 1210 real_ev = sony_nc_hotkeys_decode(event, handle); 1211 1212 if (real_ev > 0) 1213 sony_laptop_report_input_event(real_ev); 1214 else 1215 /* restore the original event for reporting */ 1216 real_ev = event; 1217 1218 break; 1219 1220 /* wlan switch */ 1221 case 0x0124: 1222 case 0x0135: 1223 /* events on this handle are reported when the 1224 * switch changes position or for battery 1225 * events. We'll notify both of them but only 1226 * update the rfkill device status when the 1227 * switch is moved. 1228 */ 1229 ev_type = KILLSWITCH; 1230 sony_call_snc_handle(handle, 0x0100, &result); 1231 real_ev = result & 0x03; 1232 1233 /* hw switch event */ 1234 if (real_ev == 1) 1235 sony_nc_rfkill_update(); 1236 1237 break; 1238 1239 case 0x0128: 1240 case 0x0146: 1241 /* Hybrid GFX switching */ 1242 sony_call_snc_handle(handle, 0x0000, &result); 1243 dprintk("GFX switch event received (reason: %s)\n", 1244 (result & 0x01) ? 1245 "switch change" : "unknown"); 1246 1247 /* verify the switch state 1248 * 1: discrete GFX 1249 * 0: integrated GFX 1250 */ 1251 sony_call_snc_handle(handle, 0x0100, &result); 1252 1253 ev_type = GFX_SWITCH; 1254 real_ev = result & 0xff; 1255 break; 1256 1257 default: 1258 dprintk("Unknown event 0x%x for handle 0x%x\n", 1259 event, handle); 1260 break; 1261 } 1262 1263 /* clear the event (and the event reason when present) */ 1264 arg = 1 << offset; 1265 sony_nc_int_call(sony_nc_acpi_handle, "SN05", &arg, &result); 1266 1267 } else { 1268 /* old style event */ 1269 ev_type = HOTKEY; 1270 sony_laptop_report_input_event(real_ev); 1271 } 1272 1273 acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev); 1274 1275 acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class, 1276 dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev); 1277 } 1278 1279 static acpi_status sony_walk_callback(acpi_handle handle, u32 level, 1280 void *context, void **return_value) 1281 { 1282 struct acpi_device_info *info; 1283 1284 if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { 1285 pr_warn("method: name: %4.4s, args %X\n", 1286 (char *)&info->name, info->param_count); 1287 1288 kfree(info); 1289 } 1290 1291 return AE_OK; 1292 } 1293 1294 /* 1295 * ACPI device 1296 */ 1297 static void sony_nc_function_setup(struct acpi_device *device, 1298 struct platform_device *pf_device) 1299 { 1300 unsigned int i, result, bitmask, arg; 1301 1302 if (!handles) 1303 return; 1304 1305 /* setup found handles here */ 1306 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { 1307 unsigned int handle = handles->cap[i]; 1308 1309 if (!handle) 1310 continue; 1311 1312 dprintk("setting up handle 0x%.4x\n", handle); 1313 1314 switch (handle) { 1315 case 0x0100: 1316 case 0x0101: 1317 case 0x0127: 1318 /* setup hotkeys */ 1319 sony_call_snc_handle(handle, 0, &result); 1320 break; 1321 case 0x0102: 1322 /* setup hotkeys */ 1323 sony_call_snc_handle(handle, 0x100, &result); 1324 break; 1325 case 0x0105: 1326 case 0x0148: 1327 /* touchpad enable/disable */ 1328 result = sony_nc_touchpad_setup(pf_device, handle); 1329 if (result) 1330 pr_err("couldn't set up touchpad control function (%d)\n", 1331 result); 1332 break; 1333 case 0x0115: 1334 case 0x0136: 1335 case 0x013f: 1336 result = sony_nc_battery_care_setup(pf_device, handle); 1337 if (result) 1338 pr_err("couldn't set up battery care function (%d)\n", 1339 result); 1340 break; 1341 case 0x0119: 1342 result = sony_nc_lid_resume_setup(pf_device); 1343 if (result) 1344 pr_err("couldn't set up lid resume function (%d)\n", 1345 result); 1346 break; 1347 case 0x0122: 1348 result = sony_nc_thermal_setup(pf_device); 1349 if (result) 1350 pr_err("couldn't set up thermal profile function (%d)\n", 1351 result); 1352 break; 1353 case 0x0131: 1354 result = sony_nc_highspeed_charging_setup(pf_device); 1355 if (result) 1356 pr_err("couldn't set up high speed charging function (%d)\n", 1357 result); 1358 break; 1359 case 0x0124: 1360 case 0x0135: 1361 result = sony_nc_rfkill_setup(device, handle); 1362 if (result) 1363 pr_err("couldn't set up rfkill support (%d)\n", 1364 result); 1365 break; 1366 case 0x0137: 1367 case 0x0143: 1368 result = sony_nc_kbd_backlight_setup(pf_device, handle); 1369 if (result) 1370 pr_err("couldn't set up keyboard backlight function (%d)\n", 1371 result); 1372 break; 1373 default: 1374 continue; 1375 } 1376 } 1377 1378 /* Enable all events */ 1379 arg = 0x10; 1380 if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) 1381 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, 1382 &result); 1383 } 1384 1385 static void sony_nc_function_cleanup(struct platform_device *pd) 1386 { 1387 unsigned int i, result, bitmask, handle; 1388 1389 /* get enabled events and disable them */ 1390 sony_nc_int_call(sony_nc_acpi_handle, "SN01", NULL, &bitmask); 1391 sony_nc_int_call(sony_nc_acpi_handle, "SN03", &bitmask, &result); 1392 1393 /* cleanup handles here */ 1394 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { 1395 1396 handle = handles->cap[i]; 1397 1398 if (!handle) 1399 continue; 1400 1401 switch (handle) { 1402 case 0x0105: 1403 case 0x0148: 1404 sony_nc_touchpad_cleanup(pd); 1405 break; 1406 case 0x0115: 1407 case 0x0136: 1408 case 0x013f: 1409 sony_nc_battery_care_cleanup(pd); 1410 break; 1411 case 0x0119: 1412 sony_nc_lid_resume_cleanup(pd); 1413 break; 1414 case 0x0122: 1415 sony_nc_thermal_cleanup(pd); 1416 break; 1417 case 0x0131: 1418 sony_nc_highspeed_charging_cleanup(pd); 1419 break; 1420 case 0x0124: 1421 case 0x0135: 1422 sony_nc_rfkill_cleanup(); 1423 break; 1424 case 0x0137: 1425 case 0x0143: 1426 sony_nc_kbd_backlight_cleanup(pd); 1427 break; 1428 default: 1429 continue; 1430 } 1431 } 1432 1433 /* finally cleanup the handles list */ 1434 sony_nc_handles_cleanup(pd); 1435 } 1436 1437 #ifdef CONFIG_PM_SLEEP 1438 static void sony_nc_function_resume(void) 1439 { 1440 unsigned int i, result, bitmask, arg; 1441 1442 dprintk("Resuming SNC device\n"); 1443 1444 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { 1445 unsigned int handle = handles->cap[i]; 1446 1447 if (!handle) 1448 continue; 1449 1450 switch (handle) { 1451 case 0x0100: 1452 case 0x0101: 1453 case 0x0127: 1454 /* re-enable hotkeys */ 1455 sony_call_snc_handle(handle, 0, &result); 1456 break; 1457 case 0x0102: 1458 /* re-enable hotkeys */ 1459 sony_call_snc_handle(handle, 0x100, &result); 1460 break; 1461 case 0x0122: 1462 sony_nc_thermal_resume(); 1463 break; 1464 case 0x0124: 1465 case 0x0135: 1466 sony_nc_rfkill_update(); 1467 break; 1468 case 0x0137: 1469 case 0x0143: 1470 sony_nc_kbd_backlight_resume(); 1471 break; 1472 default: 1473 continue; 1474 } 1475 } 1476 1477 /* Enable all events */ 1478 arg = 0x10; 1479 if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) 1480 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, 1481 &result); 1482 } 1483 1484 static int sony_nc_resume(struct device *dev) 1485 { 1486 struct sony_nc_value *item; 1487 acpi_handle handle; 1488 1489 for (item = sony_nc_values; item->name; item++) { 1490 int ret; 1491 1492 if (!item->valid) 1493 continue; 1494 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, 1495 &item->value, NULL); 1496 if (ret < 0) { 1497 pr_err("%s: %d\n", __func__, ret); 1498 break; 1499 } 1500 } 1501 1502 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", 1503 &handle))) { 1504 int arg = 1; 1505 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) 1506 dprintk("ECON Method failed\n"); 1507 } 1508 1509 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", 1510 &handle))) 1511 sony_nc_function_resume(); 1512 1513 return 0; 1514 } 1515 #endif 1516 1517 static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume); 1518 1519 static void sony_nc_rfkill_cleanup(void) 1520 { 1521 int i; 1522 1523 for (i = 0; i < N_SONY_RFKILL; i++) { 1524 if (sony_rfkill_devices[i]) { 1525 rfkill_unregister(sony_rfkill_devices[i]); 1526 rfkill_destroy(sony_rfkill_devices[i]); 1527 } 1528 } 1529 } 1530 1531 static int sony_nc_rfkill_set(void *data, bool blocked) 1532 { 1533 int result; 1534 int argument = sony_rfkill_address[(long) data] + 0x100; 1535 1536 if (!blocked) 1537 argument |= 0x030000; 1538 1539 return sony_call_snc_handle(sony_rfkill_handle, argument, &result); 1540 } 1541 1542 static const struct rfkill_ops sony_rfkill_ops = { 1543 .set_block = sony_nc_rfkill_set, 1544 }; 1545 1546 static int sony_nc_setup_rfkill(struct acpi_device *device, 1547 enum sony_nc_rfkill nc_type) 1548 { 1549 int err = 0; 1550 struct rfkill *rfk; 1551 enum rfkill_type type; 1552 const char *name; 1553 int result; 1554 bool hwblock, swblock; 1555 1556 switch (nc_type) { 1557 case SONY_WIFI: 1558 type = RFKILL_TYPE_WLAN; 1559 name = "sony-wifi"; 1560 break; 1561 case SONY_BLUETOOTH: 1562 type = RFKILL_TYPE_BLUETOOTH; 1563 name = "sony-bluetooth"; 1564 break; 1565 case SONY_WWAN: 1566 type = RFKILL_TYPE_WWAN; 1567 name = "sony-wwan"; 1568 break; 1569 case SONY_WIMAX: 1570 type = RFKILL_TYPE_WIMAX; 1571 name = "sony-wimax"; 1572 break; 1573 default: 1574 return -EINVAL; 1575 } 1576 1577 rfk = rfkill_alloc(name, &device->dev, type, 1578 &sony_rfkill_ops, (void *)nc_type); 1579 if (!rfk) 1580 return -ENOMEM; 1581 1582 if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) { 1583 rfkill_destroy(rfk); 1584 return -1; 1585 } 1586 hwblock = !(result & 0x1); 1587 1588 if (sony_call_snc_handle(sony_rfkill_handle, 1589 sony_rfkill_address[nc_type], 1590 &result) < 0) { 1591 rfkill_destroy(rfk); 1592 return -1; 1593 } 1594 swblock = !(result & 0x2); 1595 1596 rfkill_init_sw_state(rfk, swblock); 1597 rfkill_set_hw_state(rfk, hwblock); 1598 1599 err = rfkill_register(rfk); 1600 if (err) { 1601 rfkill_destroy(rfk); 1602 return err; 1603 } 1604 sony_rfkill_devices[nc_type] = rfk; 1605 return err; 1606 } 1607 1608 static void sony_nc_rfkill_update(void) 1609 { 1610 enum sony_nc_rfkill i; 1611 int result; 1612 bool hwblock; 1613 1614 sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); 1615 hwblock = !(result & 0x1); 1616 1617 for (i = 0; i < N_SONY_RFKILL; i++) { 1618 int argument = sony_rfkill_address[i]; 1619 1620 if (!sony_rfkill_devices[i]) 1621 continue; 1622 1623 if (hwblock) { 1624 if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) { 1625 /* we already know we're blocked */ 1626 } 1627 continue; 1628 } 1629 1630 sony_call_snc_handle(sony_rfkill_handle, argument, &result); 1631 rfkill_set_states(sony_rfkill_devices[i], 1632 !(result & 0x2), false); 1633 } 1634 } 1635 1636 static int sony_nc_rfkill_setup(struct acpi_device *device, 1637 unsigned int handle) 1638 { 1639 u64 offset; 1640 int i; 1641 unsigned char buffer[32] = { 0 }; 1642 1643 offset = sony_find_snc_handle(handle); 1644 sony_rfkill_handle = handle; 1645 1646 i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, 1647 32); 1648 if (i < 0) 1649 return i; 1650 1651 /* The buffer is filled with magic numbers describing the devices 1652 * available, 0xff terminates the enumeration. 1653 * Known codes: 1654 * 0x00 WLAN 1655 * 0x10 BLUETOOTH 1656 * 0x20 WWAN GPRS-EDGE 1657 * 0x21 WWAN HSDPA 1658 * 0x22 WWAN EV-DO 1659 * 0x23 WWAN GPS 1660 * 0x25 Gobi WWAN no GPS 1661 * 0x26 Gobi WWAN + GPS 1662 * 0x28 Gobi WWAN no GPS 1663 * 0x29 Gobi WWAN + GPS 1664 * 0x30 WIMAX 1665 * 0x50 Gobi WWAN no GPS 1666 * 0x51 Gobi WWAN + GPS 1667 * 0x70 no SIM card slot 1668 * 0x71 SIM card slot 1669 */ 1670 for (i = 0; i < ARRAY_SIZE(buffer); i++) { 1671 1672 if (buffer[i] == 0xff) 1673 break; 1674 1675 dprintk("Radio devices, found 0x%.2x\n", buffer[i]); 1676 1677 if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI]) 1678 sony_nc_setup_rfkill(device, SONY_WIFI); 1679 1680 if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) 1681 sony_nc_setup_rfkill(device, SONY_BLUETOOTH); 1682 1683 if (((0xf0 & buffer[i]) == 0x20 || 1684 (0xf0 & buffer[i]) == 0x50) && 1685 !sony_rfkill_devices[SONY_WWAN]) 1686 sony_nc_setup_rfkill(device, SONY_WWAN); 1687 1688 if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) 1689 sony_nc_setup_rfkill(device, SONY_WIMAX); 1690 } 1691 return 0; 1692 } 1693 1694 /* Keyboard backlight feature */ 1695 struct kbd_backlight { 1696 unsigned int handle; 1697 unsigned int base; 1698 unsigned int mode; 1699 unsigned int timeout; 1700 struct device_attribute mode_attr; 1701 struct device_attribute timeout_attr; 1702 }; 1703 1704 static struct kbd_backlight *kbdbl_ctl; 1705 1706 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) 1707 { 1708 int result; 1709 1710 if (value > 1) 1711 return -EINVAL; 1712 1713 if (sony_call_snc_handle(kbdbl_ctl->handle, 1714 (value << 0x10) | (kbdbl_ctl->base), &result)) 1715 return -EIO; 1716 1717 /* Try to turn the light on/off immediately */ 1718 sony_call_snc_handle(kbdbl_ctl->handle, 1719 (value << 0x10) | (kbdbl_ctl->base + 0x100), &result); 1720 1721 kbdbl_ctl->mode = value; 1722 1723 return 0; 1724 } 1725 1726 static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev, 1727 struct device_attribute *attr, 1728 const char *buffer, size_t count) 1729 { 1730 int ret = 0; 1731 unsigned long value; 1732 1733 if (count > 31) 1734 return -EINVAL; 1735 1736 if (kstrtoul(buffer, 10, &value)) 1737 return -EINVAL; 1738 1739 ret = __sony_nc_kbd_backlight_mode_set(value); 1740 if (ret < 0) 1741 return ret; 1742 1743 return count; 1744 } 1745 1746 static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, 1747 struct device_attribute *attr, char *buffer) 1748 { 1749 ssize_t count = 0; 1750 count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode); 1751 return count; 1752 } 1753 1754 static int __sony_nc_kbd_backlight_timeout_set(u8 value) 1755 { 1756 int result; 1757 1758 if (value > 3) 1759 return -EINVAL; 1760 1761 if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) | 1762 (kbdbl_ctl->base + 0x200), &result)) 1763 return -EIO; 1764 1765 kbdbl_ctl->timeout = value; 1766 1767 return 0; 1768 } 1769 1770 static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev, 1771 struct device_attribute *attr, 1772 const char *buffer, size_t count) 1773 { 1774 int ret = 0; 1775 unsigned long value; 1776 1777 if (count > 31) 1778 return -EINVAL; 1779 1780 if (kstrtoul(buffer, 10, &value)) 1781 return -EINVAL; 1782 1783 ret = __sony_nc_kbd_backlight_timeout_set(value); 1784 if (ret < 0) 1785 return ret; 1786 1787 return count; 1788 } 1789 1790 static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, 1791 struct device_attribute *attr, char *buffer) 1792 { 1793 ssize_t count = 0; 1794 count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout); 1795 return count; 1796 } 1797 1798 static int sony_nc_kbd_backlight_setup(struct platform_device *pd, 1799 unsigned int handle) 1800 { 1801 int result; 1802 int ret = 0; 1803 1804 /* verify the kbd backlight presence, these handles are not used for 1805 * keyboard backlight only 1806 */ 1807 ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100, 1808 &result); 1809 if (ret) 1810 return ret; 1811 1812 if ((handle == 0x0137 && !(result & 0x02)) || 1813 !(result & 0x01)) { 1814 dprintk("no backlight keyboard found\n"); 1815 return 0; 1816 } 1817 1818 kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL); 1819 if (!kbdbl_ctl) 1820 return -ENOMEM; 1821 1822 kbdbl_ctl->handle = handle; 1823 if (handle == 0x0137) 1824 kbdbl_ctl->base = 0x0C00; 1825 else 1826 kbdbl_ctl->base = 0x4000; 1827 1828 sysfs_attr_init(&kbdbl_ctl->mode_attr.attr); 1829 kbdbl_ctl->mode_attr.attr.name = "kbd_backlight"; 1830 kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR; 1831 kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show; 1832 kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store; 1833 1834 sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr); 1835 kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout"; 1836 kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; 1837 kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; 1838 kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; 1839 1840 ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr); 1841 if (ret) 1842 goto outkzalloc; 1843 1844 ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr); 1845 if (ret) 1846 goto outmode; 1847 1848 __sony_nc_kbd_backlight_mode_set(kbd_backlight); 1849 __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout); 1850 1851 return 0; 1852 1853 outmode: 1854 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); 1855 outkzalloc: 1856 kfree(kbdbl_ctl); 1857 kbdbl_ctl = NULL; 1858 return ret; 1859 } 1860 1861 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) 1862 { 1863 if (kbdbl_ctl) { 1864 int result; 1865 1866 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); 1867 device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); 1868 1869 /* restore the default hw behaviour */ 1870 sony_call_snc_handle(kbdbl_ctl->handle, 1871 kbdbl_ctl->base | 0x10000, &result); 1872 sony_call_snc_handle(kbdbl_ctl->handle, 1873 kbdbl_ctl->base + 0x200, &result); 1874 1875 kfree(kbdbl_ctl); 1876 kbdbl_ctl = NULL; 1877 } 1878 } 1879 1880 #ifdef CONFIG_PM_SLEEP 1881 static void sony_nc_kbd_backlight_resume(void) 1882 { 1883 int ignore = 0; 1884 1885 if (!kbdbl_ctl) 1886 return; 1887 1888 if (kbdbl_ctl->mode == 0) 1889 sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base, 1890 &ignore); 1891 1892 if (kbdbl_ctl->timeout != 0) 1893 sony_call_snc_handle(kbdbl_ctl->handle, 1894 (kbdbl_ctl->base + 0x200) | 1895 (kbdbl_ctl->timeout << 0x10), &ignore); 1896 } 1897 #endif 1898 1899 struct battery_care_control { 1900 struct device_attribute attrs[2]; 1901 unsigned int handle; 1902 }; 1903 static struct battery_care_control *bcare_ctl; 1904 1905 static ssize_t sony_nc_battery_care_limit_store(struct device *dev, 1906 struct device_attribute *attr, 1907 const char *buffer, size_t count) 1908 { 1909 unsigned int result, cmd; 1910 unsigned long value; 1911 1912 if (count > 31) 1913 return -EINVAL; 1914 1915 if (kstrtoul(buffer, 10, &value)) 1916 return -EINVAL; 1917 1918 /* limit values (2 bits): 1919 * 00 - none 1920 * 01 - 80% 1921 * 10 - 50% 1922 * 11 - 100% 1923 * 1924 * bit 0: 0 disable BCL, 1 enable BCL 1925 * bit 1: 1 tell to store the battery limit (see bits 6,7) too 1926 * bits 2,3: reserved 1927 * bits 4,5: store the limit into the EC 1928 * bits 6,7: store the limit into the battery 1929 */ 1930 cmd = 0; 1931 1932 if (value > 0) { 1933 if (value <= 50) 1934 cmd = 0x20; 1935 1936 else if (value <= 80) 1937 cmd = 0x10; 1938 1939 else if (value <= 100) 1940 cmd = 0x30; 1941 1942 else 1943 return -EINVAL; 1944 1945 /* 1946 * handle 0x0115 should allow storing on battery too; 1947 * handle 0x0136 same as 0x0115 + health status; 1948 * handle 0x013f, same as 0x0136 but no storing on the battery 1949 */ 1950 if (bcare_ctl->handle != 0x013f) 1951 cmd = cmd | (cmd << 2); 1952 1953 cmd = (cmd | 0x1) << 0x10; 1954 } 1955 1956 if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result)) 1957 return -EIO; 1958 1959 return count; 1960 } 1961 1962 static ssize_t sony_nc_battery_care_limit_show(struct device *dev, 1963 struct device_attribute *attr, char *buffer) 1964 { 1965 unsigned int result, status; 1966 1967 if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result)) 1968 return -EIO; 1969 1970 status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0; 1971 switch (status) { 1972 case 1: 1973 status = 80; 1974 break; 1975 case 2: 1976 status = 50; 1977 break; 1978 case 3: 1979 status = 100; 1980 break; 1981 default: 1982 status = 0; 1983 break; 1984 } 1985 1986 return snprintf(buffer, PAGE_SIZE, "%d\n", status); 1987 } 1988 1989 static ssize_t sony_nc_battery_care_health_show(struct device *dev, 1990 struct device_attribute *attr, char *buffer) 1991 { 1992 ssize_t count = 0; 1993 unsigned int health; 1994 1995 if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health)) 1996 return -EIO; 1997 1998 count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff); 1999 2000 return count; 2001 } 2002 2003 static int sony_nc_battery_care_setup(struct platform_device *pd, 2004 unsigned int handle) 2005 { 2006 int ret = 0; 2007 2008 bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL); 2009 if (!bcare_ctl) 2010 return -ENOMEM; 2011 2012 bcare_ctl->handle = handle; 2013 2014 sysfs_attr_init(&bcare_ctl->attrs[0].attr); 2015 bcare_ctl->attrs[0].attr.name = "battery_care_limiter"; 2016 bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; 2017 bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show; 2018 bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store; 2019 2020 ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]); 2021 if (ret) 2022 goto outkzalloc; 2023 2024 /* 0x0115 is for models with no health reporting capability */ 2025 if (handle == 0x0115) 2026 return 0; 2027 2028 sysfs_attr_init(&bcare_ctl->attrs[1].attr); 2029 bcare_ctl->attrs[1].attr.name = "battery_care_health"; 2030 bcare_ctl->attrs[1].attr.mode = S_IRUGO; 2031 bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show; 2032 2033 ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]); 2034 if (ret) 2035 goto outlimiter; 2036 2037 return 0; 2038 2039 outlimiter: 2040 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); 2041 2042 outkzalloc: 2043 kfree(bcare_ctl); 2044 bcare_ctl = NULL; 2045 2046 return ret; 2047 } 2048 2049 static void sony_nc_battery_care_cleanup(struct platform_device *pd) 2050 { 2051 if (bcare_ctl) { 2052 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); 2053 if (bcare_ctl->handle != 0x0115) 2054 device_remove_file(&pd->dev, &bcare_ctl->attrs[1]); 2055 2056 kfree(bcare_ctl); 2057 bcare_ctl = NULL; 2058 } 2059 } 2060 2061 struct snc_thermal_ctrl { 2062 unsigned int mode; 2063 unsigned int profiles; 2064 struct device_attribute mode_attr; 2065 struct device_attribute profiles_attr; 2066 }; 2067 static struct snc_thermal_ctrl *th_handle; 2068 2069 #define THM_PROFILE_MAX 3 2070 static const char * const snc_thermal_profiles[] = { 2071 "balanced", 2072 "silent", 2073 "performance" 2074 }; 2075 2076 static int sony_nc_thermal_mode_set(unsigned short mode) 2077 { 2078 unsigned int result; 2079 2080 /* the thermal profile seems to be a two bit bitmask: 2081 * lsb -> silent 2082 * msb -> performance 2083 * no bit set is the normal operation and is always valid 2084 * Some vaio models only have "balanced" and "performance" 2085 */ 2086 if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX) 2087 return -EINVAL; 2088 2089 if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result)) 2090 return -EIO; 2091 2092 th_handle->mode = mode; 2093 2094 return 0; 2095 } 2096 2097 static int sony_nc_thermal_mode_get(void) 2098 { 2099 unsigned int result; 2100 2101 if (sony_call_snc_handle(0x0122, 0x0100, &result)) 2102 return -EIO; 2103 2104 return result & 0xff; 2105 } 2106 2107 static ssize_t sony_nc_thermal_profiles_show(struct device *dev, 2108 struct device_attribute *attr, char *buffer) 2109 { 2110 short cnt; 2111 size_t idx = 0; 2112 2113 for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) { 2114 if (!cnt || (th_handle->profiles & cnt)) 2115 idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ", 2116 snc_thermal_profiles[cnt]); 2117 } 2118 idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n"); 2119 2120 return idx; 2121 } 2122 2123 static ssize_t sony_nc_thermal_mode_store(struct device *dev, 2124 struct device_attribute *attr, 2125 const char *buffer, size_t count) 2126 { 2127 unsigned short cmd; 2128 size_t len = count; 2129 2130 if (count == 0) 2131 return -EINVAL; 2132 2133 /* skip the newline if present */ 2134 if (buffer[len - 1] == '\n') 2135 len--; 2136 2137 for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++) 2138 if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0) 2139 break; 2140 2141 if (sony_nc_thermal_mode_set(cmd)) 2142 return -EIO; 2143 2144 return count; 2145 } 2146 2147 static ssize_t sony_nc_thermal_mode_show(struct device *dev, 2148 struct device_attribute *attr, char *buffer) 2149 { 2150 ssize_t count = 0; 2151 int mode = sony_nc_thermal_mode_get(); 2152 2153 if (mode < 0) 2154 return mode; 2155 2156 count = snprintf(buffer, PAGE_SIZE, "%s\n", snc_thermal_profiles[mode]); 2157 2158 return count; 2159 } 2160 2161 static int sony_nc_thermal_setup(struct platform_device *pd) 2162 { 2163 int ret = 0; 2164 th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL); 2165 if (!th_handle) 2166 return -ENOMEM; 2167 2168 ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles); 2169 if (ret) { 2170 pr_warn("couldn't to read the thermal profiles\n"); 2171 goto outkzalloc; 2172 } 2173 2174 ret = sony_nc_thermal_mode_get(); 2175 if (ret < 0) { 2176 pr_warn("couldn't to read the current thermal profile"); 2177 goto outkzalloc; 2178 } 2179 th_handle->mode = ret; 2180 2181 sysfs_attr_init(&th_handle->profiles_attr.attr); 2182 th_handle->profiles_attr.attr.name = "thermal_profiles"; 2183 th_handle->profiles_attr.attr.mode = S_IRUGO; 2184 th_handle->profiles_attr.show = sony_nc_thermal_profiles_show; 2185 2186 sysfs_attr_init(&th_handle->mode_attr.attr); 2187 th_handle->mode_attr.attr.name = "thermal_control"; 2188 th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; 2189 th_handle->mode_attr.show = sony_nc_thermal_mode_show; 2190 th_handle->mode_attr.store = sony_nc_thermal_mode_store; 2191 2192 ret = device_create_file(&pd->dev, &th_handle->profiles_attr); 2193 if (ret) 2194 goto outkzalloc; 2195 2196 ret = device_create_file(&pd->dev, &th_handle->mode_attr); 2197 if (ret) 2198 goto outprofiles; 2199 2200 return 0; 2201 2202 outprofiles: 2203 device_remove_file(&pd->dev, &th_handle->profiles_attr); 2204 outkzalloc: 2205 kfree(th_handle); 2206 th_handle = NULL; 2207 return ret; 2208 } 2209 2210 static void sony_nc_thermal_cleanup(struct platform_device *pd) 2211 { 2212 if (th_handle) { 2213 device_remove_file(&pd->dev, &th_handle->profiles_attr); 2214 device_remove_file(&pd->dev, &th_handle->mode_attr); 2215 kfree(th_handle); 2216 th_handle = NULL; 2217 } 2218 } 2219 2220 #ifdef CONFIG_PM_SLEEP 2221 static void sony_nc_thermal_resume(void) 2222 { 2223 unsigned int status = sony_nc_thermal_mode_get(); 2224 2225 if (status != th_handle->mode) 2226 sony_nc_thermal_mode_set(th_handle->mode); 2227 } 2228 #endif 2229 2230 /* resume on LID open */ 2231 struct snc_lid_resume_control { 2232 struct device_attribute attrs[3]; 2233 unsigned int status; 2234 }; 2235 static struct snc_lid_resume_control *lid_ctl; 2236 2237 static ssize_t sony_nc_lid_resume_store(struct device *dev, 2238 struct device_attribute *attr, 2239 const char *buffer, size_t count) 2240 { 2241 unsigned int result, pos; 2242 unsigned long value; 2243 if (count > 31) 2244 return -EINVAL; 2245 2246 if (kstrtoul(buffer, 10, &value) || value > 1) 2247 return -EINVAL; 2248 2249 /* the value we have to write to SNC is a bitmask: 2250 * +--------------+ 2251 * | S3 | S4 | S5 | 2252 * +--------------+ 2253 * 2 1 0 2254 */ 2255 if (strcmp(attr->attr.name, "lid_resume_S3") == 0) 2256 pos = 2; 2257 else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) 2258 pos = 1; 2259 else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) 2260 pos = 0; 2261 else 2262 return -EINVAL; 2263 2264 if (value) 2265 value = lid_ctl->status | (1 << pos); 2266 else 2267 value = lid_ctl->status & ~(1 << pos); 2268 2269 if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result)) 2270 return -EIO; 2271 2272 lid_ctl->status = value; 2273 2274 return count; 2275 } 2276 2277 static ssize_t sony_nc_lid_resume_show(struct device *dev, 2278 struct device_attribute *attr, char *buffer) 2279 { 2280 unsigned int pos; 2281 2282 if (strcmp(attr->attr.name, "lid_resume_S3") == 0) 2283 pos = 2; 2284 else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) 2285 pos = 1; 2286 else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) 2287 pos = 0; 2288 else 2289 return -EINVAL; 2290 2291 return snprintf(buffer, PAGE_SIZE, "%d\n", 2292 (lid_ctl->status >> pos) & 0x01); 2293 } 2294 2295 static int sony_nc_lid_resume_setup(struct platform_device *pd) 2296 { 2297 unsigned int result; 2298 int i; 2299 2300 if (sony_call_snc_handle(0x0119, 0x0000, &result)) 2301 return -EIO; 2302 2303 lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL); 2304 if (!lid_ctl) 2305 return -ENOMEM; 2306 2307 lid_ctl->status = result & 0x7; 2308 2309 sysfs_attr_init(&lid_ctl->attrs[0].attr); 2310 lid_ctl->attrs[0].attr.name = "lid_resume_S3"; 2311 lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; 2312 lid_ctl->attrs[0].show = sony_nc_lid_resume_show; 2313 lid_ctl->attrs[0].store = sony_nc_lid_resume_store; 2314 2315 sysfs_attr_init(&lid_ctl->attrs[1].attr); 2316 lid_ctl->attrs[1].attr.name = "lid_resume_S4"; 2317 lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR; 2318 lid_ctl->attrs[1].show = sony_nc_lid_resume_show; 2319 lid_ctl->attrs[1].store = sony_nc_lid_resume_store; 2320 2321 sysfs_attr_init(&lid_ctl->attrs[2].attr); 2322 lid_ctl->attrs[2].attr.name = "lid_resume_S5"; 2323 lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR; 2324 lid_ctl->attrs[2].show = sony_nc_lid_resume_show; 2325 lid_ctl->attrs[2].store = sony_nc_lid_resume_store; 2326 2327 for (i = 0; i < 3; i++) { 2328 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); 2329 if (result) 2330 goto liderror; 2331 } 2332 2333 return 0; 2334 2335 liderror: 2336 for (; i > 0; i--) 2337 device_remove_file(&pd->dev, &lid_ctl->attrs[i]); 2338 2339 kfree(lid_ctl); 2340 lid_ctl = NULL; 2341 2342 return result; 2343 } 2344 2345 static void sony_nc_lid_resume_cleanup(struct platform_device *pd) 2346 { 2347 int i; 2348 2349 if (lid_ctl) { 2350 for (i = 0; i < 3; i++) 2351 device_remove_file(&pd->dev, &lid_ctl->attrs[i]); 2352 2353 kfree(lid_ctl); 2354 lid_ctl = NULL; 2355 } 2356 } 2357 2358 /* High speed charging function */ 2359 static struct device_attribute *hsc_handle; 2360 2361 static ssize_t sony_nc_highspeed_charging_store(struct device *dev, 2362 struct device_attribute *attr, 2363 const char *buffer, size_t count) 2364 { 2365 unsigned int result; 2366 unsigned long value; 2367 2368 if (count > 31) 2369 return -EINVAL; 2370 2371 if (kstrtoul(buffer, 10, &value) || value > 1) 2372 return -EINVAL; 2373 2374 if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result)) 2375 return -EIO; 2376 2377 return count; 2378 } 2379 2380 static ssize_t sony_nc_highspeed_charging_show(struct device *dev, 2381 struct device_attribute *attr, char *buffer) 2382 { 2383 unsigned int result; 2384 2385 if (sony_call_snc_handle(0x0131, 0x0100, &result)) 2386 return -EIO; 2387 2388 return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01); 2389 } 2390 2391 static int sony_nc_highspeed_charging_setup(struct platform_device *pd) 2392 { 2393 unsigned int result; 2394 2395 if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) { 2396 /* some models advertise the handle but have no implementation 2397 * for it 2398 */ 2399 pr_info("No High Speed Charging capability found\n"); 2400 return 0; 2401 } 2402 2403 hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL); 2404 if (!hsc_handle) 2405 return -ENOMEM; 2406 2407 sysfs_attr_init(&hsc_handle->attr); 2408 hsc_handle->attr.name = "battery_highspeed_charging"; 2409 hsc_handle->attr.mode = S_IRUGO | S_IWUSR; 2410 hsc_handle->show = sony_nc_highspeed_charging_show; 2411 hsc_handle->store = sony_nc_highspeed_charging_store; 2412 2413 result = device_create_file(&pd->dev, hsc_handle); 2414 if (result) { 2415 kfree(hsc_handle); 2416 hsc_handle = NULL; 2417 return result; 2418 } 2419 2420 return 0; 2421 } 2422 2423 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd) 2424 { 2425 if (hsc_handle) { 2426 device_remove_file(&pd->dev, hsc_handle); 2427 kfree(hsc_handle); 2428 hsc_handle = NULL; 2429 } 2430 } 2431 2432 /* Touchpad enable/disable */ 2433 struct touchpad_control { 2434 struct device_attribute attr; 2435 int handle; 2436 }; 2437 static struct touchpad_control *tp_ctl; 2438 2439 static ssize_t sony_nc_touchpad_store(struct device *dev, 2440 struct device_attribute *attr, const char *buffer, size_t count) 2441 { 2442 unsigned int result; 2443 unsigned long value; 2444 2445 if (count > 31) 2446 return -EINVAL; 2447 2448 if (kstrtoul(buffer, 10, &value) || value > 1) 2449 return -EINVAL; 2450 2451 /* sysfs: 0 disabled, 1 enabled 2452 * EC: 0 enabled, 1 disabled 2453 */ 2454 if (sony_call_snc_handle(tp_ctl->handle, 2455 (!value << 0x10) | 0x100, &result)) 2456 return -EIO; 2457 2458 return count; 2459 } 2460 2461 static ssize_t sony_nc_touchpad_show(struct device *dev, 2462 struct device_attribute *attr, char *buffer) 2463 { 2464 unsigned int result; 2465 2466 if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result)) 2467 return -EINVAL; 2468 2469 return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01)); 2470 } 2471 2472 static int sony_nc_touchpad_setup(struct platform_device *pd, 2473 unsigned int handle) 2474 { 2475 int ret = 0; 2476 2477 tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL); 2478 if (!tp_ctl) 2479 return -ENOMEM; 2480 2481 tp_ctl->handle = handle; 2482 2483 sysfs_attr_init(&tp_ctl->attr.attr); 2484 tp_ctl->attr.attr.name = "touchpad"; 2485 tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR; 2486 tp_ctl->attr.show = sony_nc_touchpad_show; 2487 tp_ctl->attr.store = sony_nc_touchpad_store; 2488 2489 ret = device_create_file(&pd->dev, &tp_ctl->attr); 2490 if (ret) { 2491 kfree(tp_ctl); 2492 tp_ctl = NULL; 2493 } 2494 2495 return ret; 2496 } 2497 2498 static void sony_nc_touchpad_cleanup(struct platform_device *pd) 2499 { 2500 if (tp_ctl) { 2501 device_remove_file(&pd->dev, &tp_ctl->attr); 2502 kfree(tp_ctl); 2503 tp_ctl = NULL; 2504 } 2505 } 2506 2507 static void sony_nc_backlight_ng_read_limits(int handle, 2508 struct sony_backlight_props *props) 2509 { 2510 u64 offset; 2511 int i; 2512 int lvl_table_len = 0; 2513 u8 min = 0xff, max = 0x00; 2514 unsigned char buffer[32] = { 0 }; 2515 2516 props->handle = handle; 2517 props->offset = 0; 2518 props->maxlvl = 0xff; 2519 2520 offset = sony_find_snc_handle(handle); 2521 2522 /* try to read the boundaries from ACPI tables, if we fail the above 2523 * defaults should be reasonable 2524 */ 2525 i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, 2526 32); 2527 if (i < 0) 2528 return; 2529 2530 switch (handle) { 2531 case 0x012f: 2532 case 0x0137: 2533 lvl_table_len = 9; 2534 break; 2535 case 0x143: 2536 lvl_table_len = 16; 2537 break; 2538 } 2539 2540 /* the buffer lists brightness levels available, brightness levels are 2541 * from position 0 to 8 in the array, other values are used by ALS 2542 * control. 2543 */ 2544 for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) { 2545 2546 dprintk("Brightness level: %d\n", buffer[i]); 2547 2548 if (!buffer[i]) 2549 break; 2550 2551 if (buffer[i] > max) 2552 max = buffer[i]; 2553 if (buffer[i] < min) 2554 min = buffer[i]; 2555 } 2556 props->offset = min; 2557 props->maxlvl = max; 2558 dprintk("Brightness levels: min=%d max=%d\n", props->offset, 2559 props->maxlvl); 2560 } 2561 2562 static void sony_nc_backlight_setup(void) 2563 { 2564 acpi_handle unused; 2565 int max_brightness = 0; 2566 const struct backlight_ops *ops = NULL; 2567 struct backlight_properties props; 2568 2569 if (sony_find_snc_handle(0x12f) >= 0) { 2570 ops = &sony_backlight_ng_ops; 2571 sony_bl_props.cmd_base = 0x0100; 2572 sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); 2573 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; 2574 2575 } else if (sony_find_snc_handle(0x137) >= 0) { 2576 ops = &sony_backlight_ng_ops; 2577 sony_bl_props.cmd_base = 0x0100; 2578 sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props); 2579 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; 2580 2581 } else if (sony_find_snc_handle(0x143) >= 0) { 2582 ops = &sony_backlight_ng_ops; 2583 sony_bl_props.cmd_base = 0x3000; 2584 sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props); 2585 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; 2586 2587 } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", 2588 &unused))) { 2589 ops = &sony_backlight_ops; 2590 max_brightness = SONY_MAX_BRIGHTNESS - 1; 2591 2592 } else 2593 return; 2594 2595 memset(&props, 0, sizeof(struct backlight_properties)); 2596 props.type = BACKLIGHT_PLATFORM; 2597 props.max_brightness = max_brightness; 2598 sony_bl_props.dev = backlight_device_register("sony", NULL, 2599 &sony_bl_props, 2600 ops, &props); 2601 2602 if (IS_ERR(sony_bl_props.dev)) { 2603 pr_warn("unable to register backlight device\n"); 2604 sony_bl_props.dev = NULL; 2605 } else 2606 sony_bl_props.dev->props.brightness = 2607 ops->get_brightness(sony_bl_props.dev); 2608 } 2609 2610 static void sony_nc_backlight_cleanup(void) 2611 { 2612 if (sony_bl_props.dev) 2613 backlight_device_unregister(sony_bl_props.dev); 2614 } 2615 2616 static int sony_nc_add(struct acpi_device *device) 2617 { 2618 acpi_status status; 2619 int result = 0; 2620 acpi_handle handle; 2621 struct sony_nc_value *item; 2622 2623 pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); 2624 2625 sony_nc_acpi_device = device; 2626 strcpy(acpi_device_class(device), "sony/hotkey"); 2627 2628 sony_nc_acpi_handle = device->handle; 2629 2630 /* read device status */ 2631 result = acpi_bus_get_status(device); 2632 /* bail IFF the above call was successful and the device is not present */ 2633 if (!result && !device->status.present) { 2634 dprintk("Device not present\n"); 2635 result = -ENODEV; 2636 goto outwalk; 2637 } 2638 2639 result = sony_pf_add(); 2640 if (result) 2641 goto outpresent; 2642 2643 if (debug) { 2644 status = acpi_walk_namespace(ACPI_TYPE_METHOD, 2645 sony_nc_acpi_handle, 1, sony_walk_callback, 2646 NULL, NULL, NULL); 2647 if (ACPI_FAILURE(status)) { 2648 pr_warn("unable to walk acpi resources\n"); 2649 result = -ENODEV; 2650 goto outpresent; 2651 } 2652 } 2653 2654 result = sony_laptop_setup_input(device); 2655 if (result) { 2656 pr_err("Unable to create input devices\n"); 2657 goto outplatform; 2658 } 2659 2660 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", 2661 &handle))) { 2662 int arg = 1; 2663 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) 2664 dprintk("ECON Method failed\n"); 2665 } 2666 2667 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", 2668 &handle))) { 2669 dprintk("Doing SNC setup\n"); 2670 /* retrieve the available handles */ 2671 result = sony_nc_handles_setup(sony_pf_device); 2672 if (!result) 2673 sony_nc_function_setup(device, sony_pf_device); 2674 } 2675 2676 /* setup input devices and helper fifo */ 2677 if (acpi_video_backlight_support()) { 2678 pr_info("brightness ignored, must be controlled by ACPI video driver\n"); 2679 } else { 2680 sony_nc_backlight_setup(); 2681 } 2682 2683 /* create sony_pf sysfs attributes related to the SNC device */ 2684 for (item = sony_nc_values; item->name; ++item) { 2685 2686 if (!debug && item->debug) 2687 continue; 2688 2689 /* find the available acpiget as described in the DSDT */ 2690 for (; item->acpiget && *item->acpiget; ++item->acpiget) { 2691 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, 2692 *item->acpiget, 2693 &handle))) { 2694 dprintk("Found %s getter: %s\n", 2695 item->name, *item->acpiget); 2696 item->devattr.attr.mode |= S_IRUGO; 2697 break; 2698 } 2699 } 2700 2701 /* find the available acpiset as described in the DSDT */ 2702 for (; item->acpiset && *item->acpiset; ++item->acpiset) { 2703 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, 2704 *item->acpiset, 2705 &handle))) { 2706 dprintk("Found %s setter: %s\n", 2707 item->name, *item->acpiset); 2708 item->devattr.attr.mode |= S_IWUSR; 2709 break; 2710 } 2711 } 2712 2713 if (item->devattr.attr.mode != 0) { 2714 result = 2715 device_create_file(&sony_pf_device->dev, 2716 &item->devattr); 2717 if (result) 2718 goto out_sysfs; 2719 } 2720 } 2721 2722 return 0; 2723 2724 out_sysfs: 2725 for (item = sony_nc_values; item->name; ++item) { 2726 device_remove_file(&sony_pf_device->dev, &item->devattr); 2727 } 2728 sony_nc_backlight_cleanup(); 2729 sony_nc_function_cleanup(sony_pf_device); 2730 sony_nc_handles_cleanup(sony_pf_device); 2731 2732 outplatform: 2733 sony_laptop_remove_input(); 2734 2735 outpresent: 2736 sony_pf_remove(); 2737 2738 outwalk: 2739 sony_nc_rfkill_cleanup(); 2740 return result; 2741 } 2742 2743 static int sony_nc_remove(struct acpi_device *device) 2744 { 2745 struct sony_nc_value *item; 2746 2747 sony_nc_backlight_cleanup(); 2748 2749 sony_nc_acpi_device = NULL; 2750 2751 for (item = sony_nc_values; item->name; ++item) { 2752 device_remove_file(&sony_pf_device->dev, &item->devattr); 2753 } 2754 2755 sony_nc_function_cleanup(sony_pf_device); 2756 sony_nc_handles_cleanup(sony_pf_device); 2757 sony_pf_remove(); 2758 sony_laptop_remove_input(); 2759 dprintk(SONY_NC_DRIVER_NAME " removed.\n"); 2760 2761 return 0; 2762 } 2763 2764 static const struct acpi_device_id sony_device_ids[] = { 2765 {SONY_NC_HID, 0}, 2766 {SONY_PIC_HID, 0}, 2767 {"", 0}, 2768 }; 2769 MODULE_DEVICE_TABLE(acpi, sony_device_ids); 2770 2771 static const struct acpi_device_id sony_nc_device_ids[] = { 2772 {SONY_NC_HID, 0}, 2773 {"", 0}, 2774 }; 2775 2776 static struct acpi_driver sony_nc_driver = { 2777 .name = SONY_NC_DRIVER_NAME, 2778 .class = SONY_NC_CLASS, 2779 .ids = sony_nc_device_ids, 2780 .owner = THIS_MODULE, 2781 .ops = { 2782 .add = sony_nc_add, 2783 .remove = sony_nc_remove, 2784 .notify = sony_nc_notify, 2785 }, 2786 .drv.pm = &sony_nc_pm, 2787 }; 2788 2789 /*********** SPIC (SNY6001) Device ***********/ 2790 2791 #define SONYPI_DEVICE_TYPE1 0x00000001 2792 #define SONYPI_DEVICE_TYPE2 0x00000002 2793 #define SONYPI_DEVICE_TYPE3 0x00000004 2794 2795 #define SONYPI_TYPE1_OFFSET 0x04 2796 #define SONYPI_TYPE2_OFFSET 0x12 2797 #define SONYPI_TYPE3_OFFSET 0x12 2798 2799 struct sony_pic_ioport { 2800 struct acpi_resource_io io1; 2801 struct acpi_resource_io io2; 2802 struct list_head list; 2803 }; 2804 2805 struct sony_pic_irq { 2806 struct acpi_resource_irq irq; 2807 struct list_head list; 2808 }; 2809 2810 struct sonypi_eventtypes { 2811 u8 data; 2812 unsigned long mask; 2813 struct sonypi_event *events; 2814 }; 2815 2816 struct sony_pic_dev { 2817 struct acpi_device *acpi_dev; 2818 struct sony_pic_irq *cur_irq; 2819 struct sony_pic_ioport *cur_ioport; 2820 struct list_head interrupts; 2821 struct list_head ioports; 2822 struct mutex lock; 2823 struct sonypi_eventtypes *event_types; 2824 int (*handle_irq)(const u8, const u8); 2825 int model; 2826 u16 evport_offset; 2827 u8 camera_power; 2828 u8 bluetooth_power; 2829 u8 wwan_power; 2830 }; 2831 2832 static struct sony_pic_dev spic_dev = { 2833 .interrupts = LIST_HEAD_INIT(spic_dev.interrupts), 2834 .ioports = LIST_HEAD_INIT(spic_dev.ioports), 2835 }; 2836 2837 static int spic_drv_registered; 2838 2839 /* Event masks */ 2840 #define SONYPI_JOGGER_MASK 0x00000001 2841 #define SONYPI_CAPTURE_MASK 0x00000002 2842 #define SONYPI_FNKEY_MASK 0x00000004 2843 #define SONYPI_BLUETOOTH_MASK 0x00000008 2844 #define SONYPI_PKEY_MASK 0x00000010 2845 #define SONYPI_BACK_MASK 0x00000020 2846 #define SONYPI_HELP_MASK 0x00000040 2847 #define SONYPI_LID_MASK 0x00000080 2848 #define SONYPI_ZOOM_MASK 0x00000100 2849 #define SONYPI_THUMBPHRASE_MASK 0x00000200 2850 #define SONYPI_MEYE_MASK 0x00000400 2851 #define SONYPI_MEMORYSTICK_MASK 0x00000800 2852 #define SONYPI_BATTERY_MASK 0x00001000 2853 #define SONYPI_WIRELESS_MASK 0x00002000 2854 2855 struct sonypi_event { 2856 u8 data; 2857 u8 event; 2858 }; 2859 2860 /* The set of possible button release events */ 2861 static struct sonypi_event sonypi_releaseev[] = { 2862 { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED }, 2863 { 0, 0 } 2864 }; 2865 2866 /* The set of possible jogger events */ 2867 static struct sonypi_event sonypi_joggerev[] = { 2868 { 0x1f, SONYPI_EVENT_JOGDIAL_UP }, 2869 { 0x01, SONYPI_EVENT_JOGDIAL_DOWN }, 2870 { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED }, 2871 { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED }, 2872 { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP }, 2873 { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN }, 2874 { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED }, 2875 { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED }, 2876 { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP }, 2877 { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN }, 2878 { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED }, 2879 { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED }, 2880 { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED }, 2881 { 0, 0 } 2882 }; 2883 2884 /* The set of possible capture button events */ 2885 static struct sonypi_event sonypi_captureev[] = { 2886 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, 2887 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, 2888 { 0x40, SONYPI_EVENT_CAPTURE_PRESSED }, 2889 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, 2890 { 0, 0 } 2891 }; 2892 2893 /* The set of possible fnkeys events */ 2894 static struct sonypi_event sonypi_fnkeyev[] = { 2895 { 0x10, SONYPI_EVENT_FNKEY_ESC }, 2896 { 0x11, SONYPI_EVENT_FNKEY_F1 }, 2897 { 0x12, SONYPI_EVENT_FNKEY_F2 }, 2898 { 0x13, SONYPI_EVENT_FNKEY_F3 }, 2899 { 0x14, SONYPI_EVENT_FNKEY_F4 }, 2900 { 0x15, SONYPI_EVENT_FNKEY_F5 }, 2901 { 0x16, SONYPI_EVENT_FNKEY_F6 }, 2902 { 0x17, SONYPI_EVENT_FNKEY_F7 }, 2903 { 0x18, SONYPI_EVENT_FNKEY_F8 }, 2904 { 0x19, SONYPI_EVENT_FNKEY_F9 }, 2905 { 0x1a, SONYPI_EVENT_FNKEY_F10 }, 2906 { 0x1b, SONYPI_EVENT_FNKEY_F11 }, 2907 { 0x1c, SONYPI_EVENT_FNKEY_F12 }, 2908 { 0x1f, SONYPI_EVENT_FNKEY_RELEASED }, 2909 { 0x21, SONYPI_EVENT_FNKEY_1 }, 2910 { 0x22, SONYPI_EVENT_FNKEY_2 }, 2911 { 0x31, SONYPI_EVENT_FNKEY_D }, 2912 { 0x32, SONYPI_EVENT_FNKEY_E }, 2913 { 0x33, SONYPI_EVENT_FNKEY_F }, 2914 { 0x34, SONYPI_EVENT_FNKEY_S }, 2915 { 0x35, SONYPI_EVENT_FNKEY_B }, 2916 { 0x36, SONYPI_EVENT_FNKEY_ONLY }, 2917 { 0, 0 } 2918 }; 2919 2920 /* The set of possible program key events */ 2921 static struct sonypi_event sonypi_pkeyev[] = { 2922 { 0x01, SONYPI_EVENT_PKEY_P1 }, 2923 { 0x02, SONYPI_EVENT_PKEY_P2 }, 2924 { 0x04, SONYPI_EVENT_PKEY_P3 }, 2925 { 0x20, SONYPI_EVENT_PKEY_P1 }, 2926 { 0, 0 } 2927 }; 2928 2929 /* The set of possible bluetooth events */ 2930 static struct sonypi_event sonypi_blueev[] = { 2931 { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED }, 2932 { 0x59, SONYPI_EVENT_BLUETOOTH_ON }, 2933 { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF }, 2934 { 0, 0 } 2935 }; 2936 2937 /* The set of possible wireless events */ 2938 static struct sonypi_event sonypi_wlessev[] = { 2939 { 0x59, SONYPI_EVENT_IGNORE }, 2940 { 0x5a, SONYPI_EVENT_IGNORE }, 2941 { 0, 0 } 2942 }; 2943 2944 /* The set of possible back button events */ 2945 static struct sonypi_event sonypi_backev[] = { 2946 { 0x20, SONYPI_EVENT_BACK_PRESSED }, 2947 { 0, 0 } 2948 }; 2949 2950 /* The set of possible help button events */ 2951 static struct sonypi_event sonypi_helpev[] = { 2952 { 0x3b, SONYPI_EVENT_HELP_PRESSED }, 2953 { 0, 0 } 2954 }; 2955 2956 2957 /* The set of possible lid events */ 2958 static struct sonypi_event sonypi_lidev[] = { 2959 { 0x51, SONYPI_EVENT_LID_CLOSED }, 2960 { 0x50, SONYPI_EVENT_LID_OPENED }, 2961 { 0, 0 } 2962 }; 2963 2964 /* The set of possible zoom events */ 2965 static struct sonypi_event sonypi_zoomev[] = { 2966 { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, 2967 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, 2968 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, 2969 { 0x04, SONYPI_EVENT_ZOOM_PRESSED }, 2970 { 0, 0 } 2971 }; 2972 2973 /* The set of possible thumbphrase events */ 2974 static struct sonypi_event sonypi_thumbphraseev[] = { 2975 { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED }, 2976 { 0, 0 } 2977 }; 2978 2979 /* The set of possible motioneye camera events */ 2980 static struct sonypi_event sonypi_meyeev[] = { 2981 { 0x00, SONYPI_EVENT_MEYE_FACE }, 2982 { 0x01, SONYPI_EVENT_MEYE_OPPOSITE }, 2983 { 0, 0 } 2984 }; 2985 2986 /* The set of possible memorystick events */ 2987 static struct sonypi_event sonypi_memorystickev[] = { 2988 { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT }, 2989 { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT }, 2990 { 0, 0 } 2991 }; 2992 2993 /* The set of possible battery events */ 2994 static struct sonypi_event sonypi_batteryev[] = { 2995 { 0x20, SONYPI_EVENT_BATTERY_INSERT }, 2996 { 0x30, SONYPI_EVENT_BATTERY_REMOVE }, 2997 { 0, 0 } 2998 }; 2999 3000 /* The set of possible volume events */ 3001 static struct sonypi_event sonypi_volumeev[] = { 3002 { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED }, 3003 { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED }, 3004 { 0, 0 } 3005 }; 3006 3007 /* The set of possible brightness events */ 3008 static struct sonypi_event sonypi_brightnessev[] = { 3009 { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED }, 3010 { 0, 0 } 3011 }; 3012 3013 static struct sonypi_eventtypes type1_events[] = { 3014 { 0, 0xffffffff, sonypi_releaseev }, 3015 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, 3016 { 0x30, SONYPI_LID_MASK, sonypi_lidev }, 3017 { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, 3018 { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, 3019 { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 3020 { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, 3021 { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, 3022 { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 3023 { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, 3024 { 0 }, 3025 }; 3026 static struct sonypi_eventtypes type2_events[] = { 3027 { 0, 0xffffffff, sonypi_releaseev }, 3028 { 0x38, SONYPI_LID_MASK, sonypi_lidev }, 3029 { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, 3030 { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, 3031 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 3032 { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, 3033 { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, 3034 { 0x11, SONYPI_BACK_MASK, sonypi_backev }, 3035 { 0x21, SONYPI_HELP_MASK, sonypi_helpev }, 3036 { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, 3037 { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, 3038 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 3039 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 3040 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 3041 { 0 }, 3042 }; 3043 static struct sonypi_eventtypes type3_events[] = { 3044 { 0, 0xffffffff, sonypi_releaseev }, 3045 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 3046 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, 3047 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 3048 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 3049 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 3050 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, 3051 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, 3052 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, 3053 { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev }, 3054 { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev }, 3055 { 0 }, 3056 }; 3057 3058 /* low level spic calls */ 3059 #define ITERATIONS_LONG 10000 3060 #define ITERATIONS_SHORT 10 3061 #define wait_on_command(command, iterations) { \ 3062 unsigned int n = iterations; \ 3063 while (--n && (command)) \ 3064 udelay(1); \ 3065 if (!n) \ 3066 dprintk("command failed at %s : %s (line %d)\n", \ 3067 __FILE__, __func__, __LINE__); \ 3068 } 3069 3070 static u8 sony_pic_call1(u8 dev) 3071 { 3072 u8 v1, v2; 3073 3074 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 3075 ITERATIONS_LONG); 3076 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 3077 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); 3078 v2 = inb_p(spic_dev.cur_ioport->io1.minimum); 3079 dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1); 3080 return v2; 3081 } 3082 3083 static u8 sony_pic_call2(u8 dev, u8 fn) 3084 { 3085 u8 v1; 3086 3087 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 3088 ITERATIONS_LONG); 3089 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 3090 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, 3091 ITERATIONS_LONG); 3092 outb(fn, spic_dev.cur_ioport->io1.minimum); 3093 v1 = inb_p(spic_dev.cur_ioport->io1.minimum); 3094 dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1); 3095 return v1; 3096 } 3097 3098 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) 3099 { 3100 u8 v1; 3101 3102 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 3103 outb(dev, spic_dev.cur_ioport->io1.minimum + 4); 3104 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 3105 outb(fn, spic_dev.cur_ioport->io1.minimum); 3106 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); 3107 outb(v, spic_dev.cur_ioport->io1.minimum); 3108 v1 = inb_p(spic_dev.cur_ioport->io1.minimum); 3109 dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", 3110 dev, fn, v, v1); 3111 return v1; 3112 } 3113 3114 /* 3115 * minidrivers for SPIC models 3116 */ 3117 static int type3_handle_irq(const u8 data_mask, const u8 ev) 3118 { 3119 /* 3120 * 0x31 could mean we have to take some extra action and wait for 3121 * the next irq for some Type3 models, it will generate a new 3122 * irq and we can read new data from the device: 3123 * - 0x5c and 0x5f requires 0xA0 3124 * - 0x61 requires 0xB3 3125 */ 3126 if (data_mask == 0x31) { 3127 if (ev == 0x5c || ev == 0x5f) 3128 sony_pic_call1(0xA0); 3129 else if (ev == 0x61) 3130 sony_pic_call1(0xB3); 3131 return 0; 3132 } 3133 return 1; 3134 } 3135 3136 static void sony_pic_detect_device_type(struct sony_pic_dev *dev) 3137 { 3138 struct pci_dev *pcidev; 3139 3140 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 3141 PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 3142 if (pcidev) { 3143 dev->model = SONYPI_DEVICE_TYPE1; 3144 dev->evport_offset = SONYPI_TYPE1_OFFSET; 3145 dev->event_types = type1_events; 3146 goto out; 3147 } 3148 3149 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 3150 PCI_DEVICE_ID_INTEL_ICH6_1, NULL); 3151 if (pcidev) { 3152 dev->model = SONYPI_DEVICE_TYPE2; 3153 dev->evport_offset = SONYPI_TYPE2_OFFSET; 3154 dev->event_types = type2_events; 3155 goto out; 3156 } 3157 3158 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 3159 PCI_DEVICE_ID_INTEL_ICH7_1, NULL); 3160 if (pcidev) { 3161 dev->model = SONYPI_DEVICE_TYPE3; 3162 dev->handle_irq = type3_handle_irq; 3163 dev->evport_offset = SONYPI_TYPE3_OFFSET; 3164 dev->event_types = type3_events; 3165 goto out; 3166 } 3167 3168 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 3169 PCI_DEVICE_ID_INTEL_ICH8_4, NULL); 3170 if (pcidev) { 3171 dev->model = SONYPI_DEVICE_TYPE3; 3172 dev->handle_irq = type3_handle_irq; 3173 dev->evport_offset = SONYPI_TYPE3_OFFSET; 3174 dev->event_types = type3_events; 3175 goto out; 3176 } 3177 3178 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 3179 PCI_DEVICE_ID_INTEL_ICH9_1, NULL); 3180 if (pcidev) { 3181 dev->model = SONYPI_DEVICE_TYPE3; 3182 dev->handle_irq = type3_handle_irq; 3183 dev->evport_offset = SONYPI_TYPE3_OFFSET; 3184 dev->event_types = type3_events; 3185 goto out; 3186 } 3187 3188 /* default */ 3189 dev->model = SONYPI_DEVICE_TYPE2; 3190 dev->evport_offset = SONYPI_TYPE2_OFFSET; 3191 dev->event_types = type2_events; 3192 3193 out: 3194 if (pcidev) 3195 pci_dev_put(pcidev); 3196 3197 pr_info("detected Type%d model\n", 3198 dev->model == SONYPI_DEVICE_TYPE1 ? 1 : 3199 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); 3200 } 3201 3202 /* camera tests and poweron/poweroff */ 3203 #define SONYPI_CAMERA_PICTURE 5 3204 #define SONYPI_CAMERA_CONTROL 0x10 3205 3206 #define SONYPI_CAMERA_BRIGHTNESS 0 3207 #define SONYPI_CAMERA_CONTRAST 1 3208 #define SONYPI_CAMERA_HUE 2 3209 #define SONYPI_CAMERA_COLOR 3 3210 #define SONYPI_CAMERA_SHARPNESS 4 3211 3212 #define SONYPI_CAMERA_EXPOSURE_MASK 0xC 3213 #define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3 3214 #define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30 3215 #define SONYPI_CAMERA_MUTE_MASK 0x40 3216 3217 /* the rest don't need a loop until not 0xff */ 3218 #define SONYPI_CAMERA_AGC 6 3219 #define SONYPI_CAMERA_AGC_MASK 0x30 3220 #define SONYPI_CAMERA_SHUTTER_MASK 0x7 3221 3222 #define SONYPI_CAMERA_SHUTDOWN_REQUEST 7 3223 #define SONYPI_CAMERA_CONTROL 0x10 3224 3225 #define SONYPI_CAMERA_STATUS 7 3226 #define SONYPI_CAMERA_STATUS_READY 0x2 3227 #define SONYPI_CAMERA_STATUS_POSITION 0x4 3228 3229 #define SONYPI_DIRECTION_BACKWARDS 0x4 3230 3231 #define SONYPI_CAMERA_REVISION 8 3232 #define SONYPI_CAMERA_ROMVERSION 9 3233 3234 static int __sony_pic_camera_ready(void) 3235 { 3236 u8 v; 3237 3238 v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS); 3239 return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY)); 3240 } 3241 3242 static int __sony_pic_camera_off(void) 3243 { 3244 if (!camera) { 3245 pr_warn("camera control not enabled\n"); 3246 return -ENODEV; 3247 } 3248 3249 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, 3250 SONYPI_CAMERA_MUTE_MASK), 3251 ITERATIONS_SHORT); 3252 3253 if (spic_dev.camera_power) { 3254 sony_pic_call2(0x91, 0); 3255 spic_dev.camera_power = 0; 3256 } 3257 return 0; 3258 } 3259 3260 static int __sony_pic_camera_on(void) 3261 { 3262 int i, j, x; 3263 3264 if (!camera) { 3265 pr_warn("camera control not enabled\n"); 3266 return -ENODEV; 3267 } 3268 3269 if (spic_dev.camera_power) 3270 return 0; 3271 3272 for (j = 5; j > 0; j--) { 3273 3274 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++) 3275 msleep(10); 3276 sony_pic_call1(0x93); 3277 3278 for (i = 400; i > 0; i--) { 3279 if (__sony_pic_camera_ready()) 3280 break; 3281 msleep(10); 3282 } 3283 if (i) 3284 break; 3285 } 3286 3287 if (j == 0) { 3288 pr_warn("failed to power on camera\n"); 3289 return -ENODEV; 3290 } 3291 3292 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL, 3293 0x5a), 3294 ITERATIONS_SHORT); 3295 3296 spic_dev.camera_power = 1; 3297 return 0; 3298 } 3299 3300 /* External camera command (exported to the motion eye v4l driver) */ 3301 int sony_pic_camera_command(int command, u8 value) 3302 { 3303 if (!camera) 3304 return -EIO; 3305 3306 mutex_lock(&spic_dev.lock); 3307 3308 switch (command) { 3309 case SONY_PIC_COMMAND_SETCAMERA: 3310 if (value) 3311 __sony_pic_camera_on(); 3312 else 3313 __sony_pic_camera_off(); 3314 break; 3315 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS: 3316 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value), 3317 ITERATIONS_SHORT); 3318 break; 3319 case SONY_PIC_COMMAND_SETCAMERACONTRAST: 3320 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value), 3321 ITERATIONS_SHORT); 3322 break; 3323 case SONY_PIC_COMMAND_SETCAMERAHUE: 3324 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value), 3325 ITERATIONS_SHORT); 3326 break; 3327 case SONY_PIC_COMMAND_SETCAMERACOLOR: 3328 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value), 3329 ITERATIONS_SHORT); 3330 break; 3331 case SONY_PIC_COMMAND_SETCAMERASHARPNESS: 3332 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value), 3333 ITERATIONS_SHORT); 3334 break; 3335 case SONY_PIC_COMMAND_SETCAMERAPICTURE: 3336 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value), 3337 ITERATIONS_SHORT); 3338 break; 3339 case SONY_PIC_COMMAND_SETCAMERAAGC: 3340 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value), 3341 ITERATIONS_SHORT); 3342 break; 3343 default: 3344 pr_err("sony_pic_camera_command invalid: %d\n", command); 3345 break; 3346 } 3347 mutex_unlock(&spic_dev.lock); 3348 return 0; 3349 } 3350 EXPORT_SYMBOL(sony_pic_camera_command); 3351 3352 /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ 3353 static void __sony_pic_set_wwanpower(u8 state) 3354 { 3355 state = !!state; 3356 if (spic_dev.wwan_power == state) 3357 return; 3358 sony_pic_call2(0xB0, state); 3359 sony_pic_call1(0x82); 3360 spic_dev.wwan_power = state; 3361 } 3362 3363 static ssize_t sony_pic_wwanpower_store(struct device *dev, 3364 struct device_attribute *attr, 3365 const char *buffer, size_t count) 3366 { 3367 unsigned long value; 3368 if (count > 31) 3369 return -EINVAL; 3370 3371 if (kstrtoul(buffer, 10, &value)) 3372 return -EINVAL; 3373 3374 mutex_lock(&spic_dev.lock); 3375 __sony_pic_set_wwanpower(value); 3376 mutex_unlock(&spic_dev.lock); 3377 3378 return count; 3379 } 3380 3381 static ssize_t sony_pic_wwanpower_show(struct device *dev, 3382 struct device_attribute *attr, char *buffer) 3383 { 3384 ssize_t count; 3385 mutex_lock(&spic_dev.lock); 3386 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.wwan_power); 3387 mutex_unlock(&spic_dev.lock); 3388 return count; 3389 } 3390 3391 /* bluetooth subsystem power state */ 3392 static void __sony_pic_set_bluetoothpower(u8 state) 3393 { 3394 state = !!state; 3395 if (spic_dev.bluetooth_power == state) 3396 return; 3397 sony_pic_call2(0x96, state); 3398 sony_pic_call1(0x82); 3399 spic_dev.bluetooth_power = state; 3400 } 3401 3402 static ssize_t sony_pic_bluetoothpower_store(struct device *dev, 3403 struct device_attribute *attr, 3404 const char *buffer, size_t count) 3405 { 3406 unsigned long value; 3407 if (count > 31) 3408 return -EINVAL; 3409 3410 if (kstrtoul(buffer, 10, &value)) 3411 return -EINVAL; 3412 3413 mutex_lock(&spic_dev.lock); 3414 __sony_pic_set_bluetoothpower(value); 3415 mutex_unlock(&spic_dev.lock); 3416 3417 return count; 3418 } 3419 3420 static ssize_t sony_pic_bluetoothpower_show(struct device *dev, 3421 struct device_attribute *attr, char *buffer) 3422 { 3423 ssize_t count = 0; 3424 mutex_lock(&spic_dev.lock); 3425 count = snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power); 3426 mutex_unlock(&spic_dev.lock); 3427 return count; 3428 } 3429 3430 /* fan speed */ 3431 /* FAN0 information (reverse engineered from ACPI tables) */ 3432 #define SONY_PIC_FAN0_STATUS 0x93 3433 static int sony_pic_set_fanspeed(unsigned long value) 3434 { 3435 return ec_write(SONY_PIC_FAN0_STATUS, value); 3436 } 3437 3438 static int sony_pic_get_fanspeed(u8 *value) 3439 { 3440 return ec_read(SONY_PIC_FAN0_STATUS, value); 3441 } 3442 3443 static ssize_t sony_pic_fanspeed_store(struct device *dev, 3444 struct device_attribute *attr, 3445 const char *buffer, size_t count) 3446 { 3447 unsigned long value; 3448 if (count > 31) 3449 return -EINVAL; 3450 3451 if (kstrtoul(buffer, 10, &value)) 3452 return -EINVAL; 3453 3454 if (sony_pic_set_fanspeed(value)) 3455 return -EIO; 3456 3457 return count; 3458 } 3459 3460 static ssize_t sony_pic_fanspeed_show(struct device *dev, 3461 struct device_attribute *attr, char *buffer) 3462 { 3463 u8 value = 0; 3464 if (sony_pic_get_fanspeed(&value)) 3465 return -EIO; 3466 3467 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 3468 } 3469 3470 #define SPIC_ATTR(_name, _mode) \ 3471 struct device_attribute spic_attr_##_name = __ATTR(_name, \ 3472 _mode, sony_pic_## _name ##_show, \ 3473 sony_pic_## _name ##_store) 3474 3475 static SPIC_ATTR(bluetoothpower, 0644); 3476 static SPIC_ATTR(wwanpower, 0644); 3477 static SPIC_ATTR(fanspeed, 0644); 3478 3479 static struct attribute *spic_attributes[] = { 3480 &spic_attr_bluetoothpower.attr, 3481 &spic_attr_wwanpower.attr, 3482 &spic_attr_fanspeed.attr, 3483 NULL 3484 }; 3485 3486 static struct attribute_group spic_attribute_group = { 3487 .attrs = spic_attributes 3488 }; 3489 3490 /******** SONYPI compatibility **********/ 3491 #ifdef CONFIG_SONYPI_COMPAT 3492 3493 /* battery / brightness / temperature addresses */ 3494 #define SONYPI_BAT_FLAGS 0x81 3495 #define SONYPI_LCD_LIGHT 0x96 3496 #define SONYPI_BAT1_PCTRM 0xa0 3497 #define SONYPI_BAT1_LEFT 0xa2 3498 #define SONYPI_BAT1_MAXRT 0xa4 3499 #define SONYPI_BAT2_PCTRM 0xa8 3500 #define SONYPI_BAT2_LEFT 0xaa 3501 #define SONYPI_BAT2_MAXRT 0xac 3502 #define SONYPI_BAT1_MAXTK 0xb0 3503 #define SONYPI_BAT1_FULL 0xb2 3504 #define SONYPI_BAT2_MAXTK 0xb8 3505 #define SONYPI_BAT2_FULL 0xba 3506 #define SONYPI_TEMP_STATUS 0xC1 3507 3508 struct sonypi_compat_s { 3509 struct fasync_struct *fifo_async; 3510 struct kfifo fifo; 3511 spinlock_t fifo_lock; 3512 wait_queue_head_t fifo_proc_list; 3513 atomic_t open_count; 3514 }; 3515 static struct sonypi_compat_s sonypi_compat = { 3516 .open_count = ATOMIC_INIT(0), 3517 }; 3518 3519 static int sonypi_misc_fasync(int fd, struct file *filp, int on) 3520 { 3521 return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async); 3522 } 3523 3524 static int sonypi_misc_release(struct inode *inode, struct file *file) 3525 { 3526 atomic_dec(&sonypi_compat.open_count); 3527 return 0; 3528 } 3529 3530 static int sonypi_misc_open(struct inode *inode, struct file *file) 3531 { 3532 /* Flush input queue on first open */ 3533 unsigned long flags; 3534 3535 spin_lock_irqsave(&sonypi_compat.fifo_lock, flags); 3536 3537 if (atomic_inc_return(&sonypi_compat.open_count) == 1) 3538 kfifo_reset(&sonypi_compat.fifo); 3539 3540 spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags); 3541 3542 return 0; 3543 } 3544 3545 static ssize_t sonypi_misc_read(struct file *file, char __user *buf, 3546 size_t count, loff_t *pos) 3547 { 3548 ssize_t ret; 3549 unsigned char c; 3550 3551 if ((kfifo_len(&sonypi_compat.fifo) == 0) && 3552 (file->f_flags & O_NONBLOCK)) 3553 return -EAGAIN; 3554 3555 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, 3556 kfifo_len(&sonypi_compat.fifo) != 0); 3557 if (ret) 3558 return ret; 3559 3560 while (ret < count && 3561 (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c), 3562 &sonypi_compat.fifo_lock) == sizeof(c))) { 3563 if (put_user(c, buf++)) 3564 return -EFAULT; 3565 ret++; 3566 } 3567 3568 if (ret > 0) { 3569 struct inode *inode = file->f_path.dentry->d_inode; 3570 inode->i_atime = current_fs_time(inode->i_sb); 3571 } 3572 3573 return ret; 3574 } 3575 3576 static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) 3577 { 3578 poll_wait(file, &sonypi_compat.fifo_proc_list, wait); 3579 if (kfifo_len(&sonypi_compat.fifo)) 3580 return POLLIN | POLLRDNORM; 3581 return 0; 3582 } 3583 3584 static int ec_read16(u8 addr, u16 *value) 3585 { 3586 u8 val_lb, val_hb; 3587 if (ec_read(addr, &val_lb)) 3588 return -1; 3589 if (ec_read(addr + 1, &val_hb)) 3590 return -1; 3591 *value = val_lb | (val_hb << 8); 3592 return 0; 3593 } 3594 3595 static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, 3596 unsigned long arg) 3597 { 3598 int ret = 0; 3599 void __user *argp = (void __user *)arg; 3600 u8 val8; 3601 u16 val16; 3602 int value; 3603 3604 mutex_lock(&spic_dev.lock); 3605 switch (cmd) { 3606 case SONYPI_IOCGBRT: 3607 if (sony_bl_props.dev == NULL) { 3608 ret = -EIO; 3609 break; 3610 } 3611 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, 3612 &value)) { 3613 ret = -EIO; 3614 break; 3615 } 3616 val8 = ((value & 0xff) - 1) << 5; 3617 if (copy_to_user(argp, &val8, sizeof(val8))) 3618 ret = -EFAULT; 3619 break; 3620 case SONYPI_IOCSBRT: 3621 if (sony_bl_props.dev == NULL) { 3622 ret = -EIO; 3623 break; 3624 } 3625 if (copy_from_user(&val8, argp, sizeof(val8))) { 3626 ret = -EFAULT; 3627 break; 3628 } 3629 value = (val8 >> 5) + 1; 3630 if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value, 3631 NULL)) { 3632 ret = -EIO; 3633 break; 3634 } 3635 /* sync the backlight device status */ 3636 sony_bl_props.dev->props.brightness = 3637 sony_backlight_get_brightness(sony_bl_props.dev); 3638 break; 3639 case SONYPI_IOCGBAT1CAP: 3640 if (ec_read16(SONYPI_BAT1_FULL, &val16)) { 3641 ret = -EIO; 3642 break; 3643 } 3644 if (copy_to_user(argp, &val16, sizeof(val16))) 3645 ret = -EFAULT; 3646 break; 3647 case SONYPI_IOCGBAT1REM: 3648 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) { 3649 ret = -EIO; 3650 break; 3651 } 3652 if (copy_to_user(argp, &val16, sizeof(val16))) 3653 ret = -EFAULT; 3654 break; 3655 case SONYPI_IOCGBAT2CAP: 3656 if (ec_read16(SONYPI_BAT2_FULL, &val16)) { 3657 ret = -EIO; 3658 break; 3659 } 3660 if (copy_to_user(argp, &val16, sizeof(val16))) 3661 ret = -EFAULT; 3662 break; 3663 case SONYPI_IOCGBAT2REM: 3664 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) { 3665 ret = -EIO; 3666 break; 3667 } 3668 if (copy_to_user(argp, &val16, sizeof(val16))) 3669 ret = -EFAULT; 3670 break; 3671 case SONYPI_IOCGBATFLAGS: 3672 if (ec_read(SONYPI_BAT_FLAGS, &val8)) { 3673 ret = -EIO; 3674 break; 3675 } 3676 val8 &= 0x07; 3677 if (copy_to_user(argp, &val8, sizeof(val8))) 3678 ret = -EFAULT; 3679 break; 3680 case SONYPI_IOCGBLUE: 3681 val8 = spic_dev.bluetooth_power; 3682 if (copy_to_user(argp, &val8, sizeof(val8))) 3683 ret = -EFAULT; 3684 break; 3685 case SONYPI_IOCSBLUE: 3686 if (copy_from_user(&val8, argp, sizeof(val8))) { 3687 ret = -EFAULT; 3688 break; 3689 } 3690 __sony_pic_set_bluetoothpower(val8); 3691 break; 3692 /* FAN Controls */ 3693 case SONYPI_IOCGFAN: 3694 if (sony_pic_get_fanspeed(&val8)) { 3695 ret = -EIO; 3696 break; 3697 } 3698 if (copy_to_user(argp, &val8, sizeof(val8))) 3699 ret = -EFAULT; 3700 break; 3701 case SONYPI_IOCSFAN: 3702 if (copy_from_user(&val8, argp, sizeof(val8))) { 3703 ret = -EFAULT; 3704 break; 3705 } 3706 if (sony_pic_set_fanspeed(val8)) 3707 ret = -EIO; 3708 break; 3709 /* GET Temperature (useful under APM) */ 3710 case SONYPI_IOCGTEMP: 3711 if (ec_read(SONYPI_TEMP_STATUS, &val8)) { 3712 ret = -EIO; 3713 break; 3714 } 3715 if (copy_to_user(argp, &val8, sizeof(val8))) 3716 ret = -EFAULT; 3717 break; 3718 default: 3719 ret = -EINVAL; 3720 } 3721 mutex_unlock(&spic_dev.lock); 3722 return ret; 3723 } 3724 3725 static const struct file_operations sonypi_misc_fops = { 3726 .owner = THIS_MODULE, 3727 .read = sonypi_misc_read, 3728 .poll = sonypi_misc_poll, 3729 .open = sonypi_misc_open, 3730 .release = sonypi_misc_release, 3731 .fasync = sonypi_misc_fasync, 3732 .unlocked_ioctl = sonypi_misc_ioctl, 3733 .llseek = noop_llseek, 3734 }; 3735 3736 static struct miscdevice sonypi_misc_device = { 3737 .minor = MISC_DYNAMIC_MINOR, 3738 .name = "sonypi", 3739 .fops = &sonypi_misc_fops, 3740 }; 3741 3742 static void sonypi_compat_report_event(u8 event) 3743 { 3744 kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event, 3745 sizeof(event), &sonypi_compat.fifo_lock); 3746 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); 3747 wake_up_interruptible(&sonypi_compat.fifo_proc_list); 3748 } 3749 3750 static int sonypi_compat_init(void) 3751 { 3752 int error; 3753 3754 spin_lock_init(&sonypi_compat.fifo_lock); 3755 error = 3756 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 3757 if (error) { 3758 pr_err("kfifo_alloc failed\n"); 3759 return error; 3760 } 3761 3762 init_waitqueue_head(&sonypi_compat.fifo_proc_list); 3763 3764 if (minor != -1) 3765 sonypi_misc_device.minor = minor; 3766 error = misc_register(&sonypi_misc_device); 3767 if (error) { 3768 pr_err("misc_register failed\n"); 3769 goto err_free_kfifo; 3770 } 3771 if (minor == -1) 3772 pr_info("device allocated minor is %d\n", 3773 sonypi_misc_device.minor); 3774 3775 return 0; 3776 3777 err_free_kfifo: 3778 kfifo_free(&sonypi_compat.fifo); 3779 return error; 3780 } 3781 3782 static void sonypi_compat_exit(void) 3783 { 3784 misc_deregister(&sonypi_misc_device); 3785 kfifo_free(&sonypi_compat.fifo); 3786 } 3787 #else 3788 static int sonypi_compat_init(void) { return 0; } 3789 static void sonypi_compat_exit(void) { } 3790 static void sonypi_compat_report_event(u8 event) { } 3791 #endif /* CONFIG_SONYPI_COMPAT */ 3792 3793 /* 3794 * ACPI callbacks 3795 */ 3796 static acpi_status 3797 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) 3798 { 3799 u32 i; 3800 struct sony_pic_dev *dev = (struct sony_pic_dev *)context; 3801 3802 switch (resource->type) { 3803 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 3804 { 3805 /* start IO enumeration */ 3806 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); 3807 if (!ioport) 3808 return AE_ERROR; 3809 3810 list_add(&ioport->list, &dev->ioports); 3811 return AE_OK; 3812 } 3813 3814 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 3815 /* end IO enumeration */ 3816 return AE_OK; 3817 3818 case ACPI_RESOURCE_TYPE_IRQ: 3819 { 3820 struct acpi_resource_irq *p = &resource->data.irq; 3821 struct sony_pic_irq *interrupt = NULL; 3822 if (!p || !p->interrupt_count) { 3823 /* 3824 * IRQ descriptors may have no IRQ# bits set, 3825 * particularly those those w/ _STA disabled 3826 */ 3827 dprintk("Blank IRQ resource\n"); 3828 return AE_OK; 3829 } 3830 for (i = 0; i < p->interrupt_count; i++) { 3831 if (!p->interrupts[i]) { 3832 pr_warn("Invalid IRQ %d\n", 3833 p->interrupts[i]); 3834 continue; 3835 } 3836 interrupt = kzalloc(sizeof(*interrupt), 3837 GFP_KERNEL); 3838 if (!interrupt) 3839 return AE_ERROR; 3840 3841 list_add(&interrupt->list, &dev->interrupts); 3842 interrupt->irq.triggering = p->triggering; 3843 interrupt->irq.polarity = p->polarity; 3844 interrupt->irq.sharable = p->sharable; 3845 interrupt->irq.interrupt_count = 1; 3846 interrupt->irq.interrupts[0] = p->interrupts[i]; 3847 } 3848 return AE_OK; 3849 } 3850 case ACPI_RESOURCE_TYPE_IO: 3851 { 3852 struct acpi_resource_io *io = &resource->data.io; 3853 struct sony_pic_ioport *ioport = 3854 list_first_entry(&dev->ioports, struct sony_pic_ioport, list); 3855 if (!io) { 3856 dprintk("Blank IO resource\n"); 3857 return AE_OK; 3858 } 3859 3860 if (!ioport->io1.minimum) { 3861 memcpy(&ioport->io1, io, sizeof(*io)); 3862 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum, 3863 ioport->io1.address_length); 3864 } 3865 else if (!ioport->io2.minimum) { 3866 memcpy(&ioport->io2, io, sizeof(*io)); 3867 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum, 3868 ioport->io2.address_length); 3869 } 3870 else { 3871 pr_err("Unknown SPIC Type, more than 2 IO Ports\n"); 3872 return AE_ERROR; 3873 } 3874 return AE_OK; 3875 } 3876 default: 3877 dprintk("Resource %d isn't an IRQ nor an IO port\n", 3878 resource->type); 3879 3880 case ACPI_RESOURCE_TYPE_END_TAG: 3881 return AE_OK; 3882 } 3883 return AE_CTRL_TERMINATE; 3884 } 3885 3886 static int sony_pic_possible_resources(struct acpi_device *device) 3887 { 3888 int result = 0; 3889 acpi_status status = AE_OK; 3890 3891 if (!device) 3892 return -EINVAL; 3893 3894 /* get device status */ 3895 /* see acpi_pci_link_get_current acpi_pci_link_get_possible */ 3896 dprintk("Evaluating _STA\n"); 3897 result = acpi_bus_get_status(device); 3898 if (result) { 3899 pr_warn("Unable to read status\n"); 3900 goto end; 3901 } 3902 3903 if (!device->status.enabled) 3904 dprintk("Device disabled\n"); 3905 else 3906 dprintk("Device enabled\n"); 3907 3908 /* 3909 * Query and parse 'method' 3910 */ 3911 dprintk("Evaluating %s\n", METHOD_NAME__PRS); 3912 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS, 3913 sony_pic_read_possible_resource, &spic_dev); 3914 if (ACPI_FAILURE(status)) { 3915 pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS); 3916 result = -ENODEV; 3917 } 3918 end: 3919 return result; 3920 } 3921 3922 /* 3923 * Disable the spic device by calling its _DIS method 3924 */ 3925 static int sony_pic_disable(struct acpi_device *device) 3926 { 3927 acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL, 3928 NULL); 3929 3930 if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND) 3931 return -ENXIO; 3932 3933 dprintk("Device disabled\n"); 3934 return 0; 3935 } 3936 3937 3938 /* 3939 * Based on drivers/acpi/pci_link.c:acpi_pci_link_set 3940 * 3941 * Call _SRS to set current resources 3942 */ 3943 static int sony_pic_enable(struct acpi_device *device, 3944 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq) 3945 { 3946 acpi_status status; 3947 int result = 0; 3948 /* Type 1 resource layout is: 3949 * IO 3950 * IO 3951 * IRQNoFlags 3952 * End 3953 * 3954 * Type 2 and 3 resource layout is: 3955 * IO 3956 * IRQNoFlags 3957 * End 3958 */ 3959 struct { 3960 struct acpi_resource res1; 3961 struct acpi_resource res2; 3962 struct acpi_resource res3; 3963 struct acpi_resource res4; 3964 } *resource; 3965 struct acpi_buffer buffer = { 0, NULL }; 3966 3967 if (!ioport || !irq) 3968 return -EINVAL; 3969 3970 /* init acpi_buffer */ 3971 resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL); 3972 if (!resource) 3973 return -ENOMEM; 3974 3975 buffer.length = sizeof(*resource) + 1; 3976 buffer.pointer = resource; 3977 3978 /* setup Type 1 resources */ 3979 if (spic_dev.model == SONYPI_DEVICE_TYPE1) { 3980 3981 /* setup io resources */ 3982 resource->res1.type = ACPI_RESOURCE_TYPE_IO; 3983 resource->res1.length = sizeof(struct acpi_resource); 3984 memcpy(&resource->res1.data.io, &ioport->io1, 3985 sizeof(struct acpi_resource_io)); 3986 3987 resource->res2.type = ACPI_RESOURCE_TYPE_IO; 3988 resource->res2.length = sizeof(struct acpi_resource); 3989 memcpy(&resource->res2.data.io, &ioport->io2, 3990 sizeof(struct acpi_resource_io)); 3991 3992 /* setup irq resource */ 3993 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ; 3994 resource->res3.length = sizeof(struct acpi_resource); 3995 memcpy(&resource->res3.data.irq, &irq->irq, 3996 sizeof(struct acpi_resource_irq)); 3997 /* we requested a shared irq */ 3998 resource->res3.data.irq.sharable = ACPI_SHARED; 3999 4000 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG; 4001 4002 } 4003 /* setup Type 2/3 resources */ 4004 else { 4005 /* setup io resource */ 4006 resource->res1.type = ACPI_RESOURCE_TYPE_IO; 4007 resource->res1.length = sizeof(struct acpi_resource); 4008 memcpy(&resource->res1.data.io, &ioport->io1, 4009 sizeof(struct acpi_resource_io)); 4010 4011 /* setup irq resource */ 4012 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ; 4013 resource->res2.length = sizeof(struct acpi_resource); 4014 memcpy(&resource->res2.data.irq, &irq->irq, 4015 sizeof(struct acpi_resource_irq)); 4016 /* we requested a shared irq */ 4017 resource->res2.data.irq.sharable = ACPI_SHARED; 4018 4019 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG; 4020 } 4021 4022 /* Attempt to set the resource */ 4023 dprintk("Evaluating _SRS\n"); 4024 status = acpi_set_current_resources(device->handle, &buffer); 4025 4026 /* check for total failure */ 4027 if (ACPI_FAILURE(status)) { 4028 pr_err("Error evaluating _SRS\n"); 4029 result = -ENODEV; 4030 goto end; 4031 } 4032 4033 /* Necessary device initializations calls (from sonypi) */ 4034 sony_pic_call1(0x82); 4035 sony_pic_call2(0x81, 0xff); 4036 sony_pic_call1(compat ? 0x92 : 0x82); 4037 4038 end: 4039 kfree(resource); 4040 return result; 4041 } 4042 4043 /***************** 4044 * 4045 * ISR: some event is available 4046 * 4047 *****************/ 4048 static irqreturn_t sony_pic_irq(int irq, void *dev_id) 4049 { 4050 int i, j; 4051 u8 ev = 0; 4052 u8 data_mask = 0; 4053 u8 device_event = 0; 4054 4055 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 4056 4057 ev = inb_p(dev->cur_ioport->io1.minimum); 4058 if (dev->cur_ioport->io2.minimum) 4059 data_mask = inb_p(dev->cur_ioport->io2.minimum); 4060 else 4061 data_mask = inb_p(dev->cur_ioport->io1.minimum + 4062 dev->evport_offset); 4063 4064 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 4065 ev, data_mask, dev->cur_ioport->io1.minimum, 4066 dev->evport_offset); 4067 4068 if (ev == 0x00 || ev == 0xff) 4069 return IRQ_HANDLED; 4070 4071 for (i = 0; dev->event_types[i].mask; i++) { 4072 4073 if ((data_mask & dev->event_types[i].data) != 4074 dev->event_types[i].data) 4075 continue; 4076 4077 if (!(mask & dev->event_types[i].mask)) 4078 continue; 4079 4080 for (j = 0; dev->event_types[i].events[j].event; j++) { 4081 if (ev == dev->event_types[i].events[j].data) { 4082 device_event = 4083 dev->event_types[i].events[j].event; 4084 /* some events may require ignoring */ 4085 if (!device_event) 4086 return IRQ_HANDLED; 4087 goto found; 4088 } 4089 } 4090 } 4091 /* Still not able to decode the event try to pass 4092 * it over to the minidriver 4093 */ 4094 if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0) 4095 return IRQ_HANDLED; 4096 4097 dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 4098 ev, data_mask, dev->cur_ioport->io1.minimum, 4099 dev->evport_offset); 4100 return IRQ_HANDLED; 4101 4102 found: 4103 sony_laptop_report_input_event(device_event); 4104 acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); 4105 sonypi_compat_report_event(device_event); 4106 return IRQ_HANDLED; 4107 } 4108 4109 /***************** 4110 * 4111 * ACPI driver 4112 * 4113 *****************/ 4114 static int sony_pic_remove(struct acpi_device *device) 4115 { 4116 struct sony_pic_ioport *io, *tmp_io; 4117 struct sony_pic_irq *irq, *tmp_irq; 4118 4119 if (sony_pic_disable(device)) { 4120 pr_err("Couldn't disable device\n"); 4121 return -ENXIO; 4122 } 4123 4124 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 4125 release_region(spic_dev.cur_ioport->io1.minimum, 4126 spic_dev.cur_ioport->io1.address_length); 4127 if (spic_dev.cur_ioport->io2.minimum) 4128 release_region(spic_dev.cur_ioport->io2.minimum, 4129 spic_dev.cur_ioport->io2.address_length); 4130 4131 sonypi_compat_exit(); 4132 4133 sony_laptop_remove_input(); 4134 4135 /* pf attrs */ 4136 sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group); 4137 sony_pf_remove(); 4138 4139 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) { 4140 list_del(&io->list); 4141 kfree(io); 4142 } 4143 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) { 4144 list_del(&irq->list); 4145 kfree(irq); 4146 } 4147 spic_dev.cur_ioport = NULL; 4148 spic_dev.cur_irq = NULL; 4149 4150 dprintk(SONY_PIC_DRIVER_NAME " removed.\n"); 4151 return 0; 4152 } 4153 4154 static int sony_pic_add(struct acpi_device *device) 4155 { 4156 int result; 4157 struct sony_pic_ioport *io, *tmp_io; 4158 struct sony_pic_irq *irq, *tmp_irq; 4159 4160 pr_info("%s v%s\n", SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); 4161 4162 spic_dev.acpi_dev = device; 4163 strcpy(acpi_device_class(device), "sony/hotkey"); 4164 sony_pic_detect_device_type(&spic_dev); 4165 mutex_init(&spic_dev.lock); 4166 4167 /* read _PRS resources */ 4168 result = sony_pic_possible_resources(device); 4169 if (result) { 4170 pr_err("Unable to read possible resources\n"); 4171 goto err_free_resources; 4172 } 4173 4174 /* setup input devices and helper fifo */ 4175 result = sony_laptop_setup_input(device); 4176 if (result) { 4177 pr_err("Unable to create input devices\n"); 4178 goto err_free_resources; 4179 } 4180 4181 if (sonypi_compat_init()) 4182 goto err_remove_input; 4183 4184 /* request io port */ 4185 list_for_each_entry_reverse(io, &spic_dev.ioports, list) { 4186 if (request_region(io->io1.minimum, io->io1.address_length, 4187 "Sony Programmable I/O Device")) { 4188 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n", 4189 io->io1.minimum, io->io1.maximum, 4190 io->io1.address_length); 4191 /* Type 1 have 2 ioports */ 4192 if (io->io2.minimum) { 4193 if (request_region(io->io2.minimum, 4194 io->io2.address_length, 4195 "Sony Programmable I/O Device")) { 4196 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n", 4197 io->io2.minimum, io->io2.maximum, 4198 io->io2.address_length); 4199 spic_dev.cur_ioport = io; 4200 break; 4201 } 4202 else { 4203 dprintk("Unable to get I/O port2: " 4204 "0x%.4x (0x%.4x) + 0x%.2x\n", 4205 io->io2.minimum, io->io2.maximum, 4206 io->io2.address_length); 4207 release_region(io->io1.minimum, 4208 io->io1.address_length); 4209 } 4210 } 4211 else { 4212 spic_dev.cur_ioport = io; 4213 break; 4214 } 4215 } 4216 } 4217 if (!spic_dev.cur_ioport) { 4218 pr_err("Failed to request_region\n"); 4219 result = -ENODEV; 4220 goto err_remove_compat; 4221 } 4222 4223 /* request IRQ */ 4224 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) { 4225 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, 4226 0, "sony-laptop", &spic_dev)) { 4227 dprintk("IRQ: %d - triggering: %d - " 4228 "polarity: %d - shr: %d\n", 4229 irq->irq.interrupts[0], 4230 irq->irq.triggering, 4231 irq->irq.polarity, 4232 irq->irq.sharable); 4233 spic_dev.cur_irq = irq; 4234 break; 4235 } 4236 } 4237 if (!spic_dev.cur_irq) { 4238 pr_err("Failed to request_irq\n"); 4239 result = -ENODEV; 4240 goto err_release_region; 4241 } 4242 4243 /* set resource status _SRS */ 4244 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq); 4245 if (result) { 4246 pr_err("Couldn't enable device\n"); 4247 goto err_free_irq; 4248 } 4249 4250 spic_dev.bluetooth_power = -1; 4251 /* create device attributes */ 4252 result = sony_pf_add(); 4253 if (result) 4254 goto err_disable_device; 4255 4256 result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group); 4257 if (result) 4258 goto err_remove_pf; 4259 4260 return 0; 4261 4262 err_remove_pf: 4263 sony_pf_remove(); 4264 4265 err_disable_device: 4266 sony_pic_disable(device); 4267 4268 err_free_irq: 4269 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 4270 4271 err_release_region: 4272 release_region(spic_dev.cur_ioport->io1.minimum, 4273 spic_dev.cur_ioport->io1.address_length); 4274 if (spic_dev.cur_ioport->io2.minimum) 4275 release_region(spic_dev.cur_ioport->io2.minimum, 4276 spic_dev.cur_ioport->io2.address_length); 4277 4278 err_remove_compat: 4279 sonypi_compat_exit(); 4280 4281 err_remove_input: 4282 sony_laptop_remove_input(); 4283 4284 err_free_resources: 4285 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) { 4286 list_del(&io->list); 4287 kfree(io); 4288 } 4289 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) { 4290 list_del(&irq->list); 4291 kfree(irq); 4292 } 4293 spic_dev.cur_ioport = NULL; 4294 spic_dev.cur_irq = NULL; 4295 4296 return result; 4297 } 4298 4299 #ifdef CONFIG_PM_SLEEP 4300 static int sony_pic_suspend(struct device *dev) 4301 { 4302 if (sony_pic_disable(to_acpi_device(dev))) 4303 return -ENXIO; 4304 return 0; 4305 } 4306 4307 static int sony_pic_resume(struct device *dev) 4308 { 4309 sony_pic_enable(to_acpi_device(dev), 4310 spic_dev.cur_ioport, spic_dev.cur_irq); 4311 return 0; 4312 } 4313 #endif 4314 4315 static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume); 4316 4317 static const struct acpi_device_id sony_pic_device_ids[] = { 4318 {SONY_PIC_HID, 0}, 4319 {"", 0}, 4320 }; 4321 4322 static struct acpi_driver sony_pic_driver = { 4323 .name = SONY_PIC_DRIVER_NAME, 4324 .class = SONY_PIC_CLASS, 4325 .ids = sony_pic_device_ids, 4326 .owner = THIS_MODULE, 4327 .ops = { 4328 .add = sony_pic_add, 4329 .remove = sony_pic_remove, 4330 }, 4331 .drv.pm = &sony_pic_pm, 4332 }; 4333 4334 static struct dmi_system_id __initdata sonypi_dmi_table[] = { 4335 { 4336 .ident = "Sony Vaio", 4337 .matches = { 4338 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 4339 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"), 4340 }, 4341 }, 4342 { 4343 .ident = "Sony Vaio", 4344 .matches = { 4345 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 4346 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"), 4347 }, 4348 }, 4349 { } 4350 }; 4351 4352 static int __init sony_laptop_init(void) 4353 { 4354 int result; 4355 4356 if (!no_spic && dmi_check_system(sonypi_dmi_table)) { 4357 result = acpi_bus_register_driver(&sony_pic_driver); 4358 if (result) { 4359 pr_err("Unable to register SPIC driver\n"); 4360 goto out; 4361 } 4362 spic_drv_registered = 1; 4363 } 4364 4365 result = acpi_bus_register_driver(&sony_nc_driver); 4366 if (result) { 4367 pr_err("Unable to register SNC driver\n"); 4368 goto out_unregister_pic; 4369 } 4370 4371 return 0; 4372 4373 out_unregister_pic: 4374 if (spic_drv_registered) 4375 acpi_bus_unregister_driver(&sony_pic_driver); 4376 out: 4377 return result; 4378 } 4379 4380 static void __exit sony_laptop_exit(void) 4381 { 4382 acpi_bus_unregister_driver(&sony_nc_driver); 4383 if (spic_drv_registered) 4384 acpi_bus_unregister_driver(&sony_pic_driver); 4385 } 4386 4387 module_init(sony_laptop_init); 4388 module_exit(sony_laptop_exit); 4389