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