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