0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0032
0033 #include <linux/kernel.h>
0034 #include <linux/module.h>
0035 #include <linux/moduleparam.h>
0036 #include <linux/init.h>
0037 #include <linux/types.h>
0038 #include <linux/backlight.h>
0039 #include <linux/platform_device.h>
0040 #include <linux/err.h>
0041 #include <linux/dmi.h>
0042 #include <linux/pci.h>
0043 #include <linux/interrupt.h>
0044 #include <linux/delay.h>
0045 #include <linux/input.h>
0046 #include <linux/kfifo.h>
0047 #include <linux/workqueue.h>
0048 #include <linux/acpi.h>
0049 #include <linux/slab.h>
0050 #include <linux/sonypi.h>
0051 #include <linux/sony-laptop.h>
0052 #include <linux/rfkill.h>
0053 #ifdef CONFIG_SONYPI_COMPAT
0054 #include <linux/poll.h>
0055 #include <linux/miscdevice.h>
0056 #endif
0057 #include <linux/uaccess.h>
0058 #include <acpi/video.h>
0059
0060 #define dprintk(fmt, ...) \
0061 do { \
0062 if (debug) \
0063 pr_warn(fmt, ##__VA_ARGS__); \
0064 } while (0)
0065
0066 #define SONY_NC_CLASS "sony-nc"
0067 #define SONY_NC_HID "SNY5001"
0068 #define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver"
0069
0070 #define SONY_PIC_CLASS "sony-pic"
0071 #define SONY_PIC_HID "SNY6001"
0072 #define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"
0073
0074 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
0075 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
0076 MODULE_LICENSE("GPL");
0077
0078 static int debug;
0079 module_param(debug, int, 0);
0080 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
0081 "the development of this driver");
0082
0083 static int no_spic;
0084 module_param(no_spic, int, 0444);
0085 MODULE_PARM_DESC(no_spic,
0086 "set this if you don't want to enable the SPIC device");
0087
0088 static int compat;
0089 module_param(compat, int, 0444);
0090 MODULE_PARM_DESC(compat,
0091 "set this if you want to enable backward compatibility mode");
0092
0093 static unsigned long mask = 0xffffffff;
0094 module_param(mask, ulong, 0644);
0095 MODULE_PARM_DESC(mask,
0096 "set this to the mask of event you want to enable (see doc)");
0097
0098 static int camera;
0099 module_param(camera, int, 0444);
0100 MODULE_PARM_DESC(camera,
0101 "set this to 1 to enable Motion Eye camera controls "
0102 "(only use it if you have a C1VE or C1VN model)");
0103
0104 #ifdef CONFIG_SONYPI_COMPAT
0105 static int minor = -1;
0106 module_param(minor, int, 0);
0107 MODULE_PARM_DESC(minor,
0108 "minor number of the misc device for the SPIC compatibility code, "
0109 "default is -1 (automatic)");
0110 #endif
0111
0112 static int kbd_backlight = -1;
0113 module_param(kbd_backlight, int, 0444);
0114 MODULE_PARM_DESC(kbd_backlight,
0115 "set this to 0 to disable keyboard backlight, "
0116 "1 to enable it with automatic control and 2 to have it always "
0117 "on (default: no change from current value)");
0118
0119 static int kbd_backlight_timeout = -1;
0120 module_param(kbd_backlight_timeout, int, 0444);
0121 MODULE_PARM_DESC(kbd_backlight_timeout,
0122 "meaningful values vary from 0 to 3 and their meaning depends "
0123 "on the model (default: no change from current value)");
0124
0125 #ifdef CONFIG_PM_SLEEP
0126 static void sony_nc_thermal_resume(void);
0127 #endif
0128 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
0129 unsigned int handle);
0130 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd,
0131 unsigned int handle);
0132
0133 static int sony_nc_battery_care_setup(struct platform_device *pd,
0134 unsigned int handle);
0135 static void sony_nc_battery_care_cleanup(struct platform_device *pd);
0136
0137 static int sony_nc_thermal_setup(struct platform_device *pd);
0138 static void sony_nc_thermal_cleanup(struct platform_device *pd);
0139
0140 static int sony_nc_lid_resume_setup(struct platform_device *pd,
0141 unsigned int handle);
0142 static void sony_nc_lid_resume_cleanup(struct platform_device *pd);
0143
0144 static int sony_nc_gfx_switch_setup(struct platform_device *pd,
0145 unsigned int handle);
0146 static void sony_nc_gfx_switch_cleanup(struct platform_device *pd);
0147 static int __sony_nc_gfx_switch_status_get(void);
0148
0149 static int sony_nc_highspeed_charging_setup(struct platform_device *pd);
0150 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd);
0151
0152 static int sony_nc_lowbatt_setup(struct platform_device *pd);
0153 static void sony_nc_lowbatt_cleanup(struct platform_device *pd);
0154
0155 static int sony_nc_fanspeed_setup(struct platform_device *pd);
0156 static void sony_nc_fanspeed_cleanup(struct platform_device *pd);
0157
0158 static int sony_nc_usb_charge_setup(struct platform_device *pd);
0159 static void sony_nc_usb_charge_cleanup(struct platform_device *pd);
0160
0161 static int sony_nc_panelid_setup(struct platform_device *pd);
0162 static void sony_nc_panelid_cleanup(struct platform_device *pd);
0163
0164 static int sony_nc_smart_conn_setup(struct platform_device *pd);
0165 static void sony_nc_smart_conn_cleanup(struct platform_device *pd);
0166
0167 static int sony_nc_touchpad_setup(struct platform_device *pd,
0168 unsigned int handle);
0169 static void sony_nc_touchpad_cleanup(struct platform_device *pd);
0170
0171 enum sony_nc_rfkill {
0172 SONY_WIFI,
0173 SONY_BLUETOOTH,
0174 SONY_WWAN,
0175 SONY_WIMAX,
0176 N_SONY_RFKILL,
0177 };
0178
0179 static int sony_rfkill_handle;
0180 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
0181 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
0182 static int sony_nc_rfkill_setup(struct acpi_device *device,
0183 unsigned int handle);
0184 static void sony_nc_rfkill_cleanup(void);
0185 static void sony_nc_rfkill_update(void);
0186
0187
0188
0189 #define SONY_LAPTOP_BUF_SIZE 128
0190 struct sony_laptop_input_s {
0191 atomic_t users;
0192 struct input_dev *jog_dev;
0193 struct input_dev *key_dev;
0194 struct kfifo fifo;
0195 spinlock_t fifo_lock;
0196 struct timer_list release_key_timer;
0197 };
0198
0199 static struct sony_laptop_input_s sony_laptop_input = {
0200 .users = ATOMIC_INIT(0),
0201 };
0202
0203 struct sony_laptop_keypress {
0204 struct input_dev *dev;
0205 int key;
0206 };
0207
0208
0209
0210
0211 static const int sony_laptop_input_index[] = {
0212 -1,
0213 -1,
0214 -1,
0215 -1,
0216 -1,
0217 -1,
0218 -1,
0219 0,
0220 1,
0221 2,
0222 3,
0223 4,
0224 5,
0225 6,
0226 7,
0227 8,
0228 9,
0229 10,
0230 11,
0231 12,
0232 13,
0233 14,
0234 15,
0235 16,
0236 17,
0237 18,
0238 19,
0239 20,
0240 21,
0241 22,
0242 23,
0243 24,
0244 25,
0245 26,
0246 27,
0247 28,
0248 -1,
0249 -1,
0250 29,
0251 30,
0252 31,
0253 32,
0254 33,
0255 34,
0256 35,
0257 36,
0258 37,
0259 38,
0260 39,
0261 40,
0262 41,
0263 42,
0264 43,
0265 44,
0266 45,
0267 46,
0268 -1,
0269 -1,
0270 -1,
0271 -1,
0272 47,
0273 48,
0274 49,
0275 50,
0276 51,
0277 52,
0278 53,
0279 54,
0280 55,
0281 56,
0282 57,
0283 -1,
0284 58,
0285 59,
0286 };
0287
0288 static int sony_laptop_input_keycode_map[] = {
0289 KEY_CAMERA,
0290 KEY_RESERVED,
0291 KEY_RESERVED,
0292 KEY_RESERVED,
0293 KEY_FN_ESC,
0294 KEY_FN_F1,
0295 KEY_FN_F2,
0296 KEY_FN_F3,
0297 KEY_FN_F4,
0298 KEY_FN_F5,
0299 KEY_FN_F6,
0300 KEY_FN_F7,
0301 KEY_FN_F8,
0302 KEY_FN_F9,
0303 KEY_FN_F10,
0304 KEY_FN_F11,
0305 KEY_FN_F12,
0306 KEY_FN_1,
0307 KEY_FN_2,
0308 KEY_FN_D,
0309 KEY_FN_E,
0310 KEY_FN_F,
0311 KEY_FN_S,
0312 KEY_FN_B,
0313 KEY_BLUETOOTH,
0314 KEY_PROG1,
0315 KEY_PROG2,
0316 KEY_PROG3,
0317 KEY_BACK,
0318 KEY_BLUETOOTH,
0319 KEY_BLUETOOTH,
0320 KEY_HELP,
0321 KEY_FN,
0322 KEY_RESERVED,
0323 KEY_RESERVED,
0324 KEY_RESERVED,
0325 KEY_RESERVED,
0326 KEY_RESERVED,
0327 KEY_RESERVED,
0328 KEY_RESERVED,
0329 KEY_RESERVED,
0330 KEY_ZOOM,
0331 BTN_THUMB,
0332 KEY_RESERVED,
0333 KEY_RESERVED,
0334 KEY_RESERVED,
0335 KEY_RESERVED,
0336 KEY_WLAN,
0337 KEY_WLAN,
0338 KEY_ZOOMIN,
0339 KEY_ZOOMOUT,
0340 KEY_EJECTCD,
0341 KEY_F13,
0342 KEY_PROG4,
0343 KEY_F14,
0344 KEY_F15,
0345 KEY_VOLUMEUP,
0346 KEY_VOLUMEDOWN,
0347 KEY_MEDIA,
0348 KEY_VENDOR,
0349 };
0350
0351
0352 static void do_sony_laptop_release_key(struct timer_list *unused)
0353 {
0354 struct sony_laptop_keypress kp;
0355 unsigned long flags;
0356
0357 spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
0358
0359 if (kfifo_out(&sony_laptop_input.fifo,
0360 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
0361 input_report_key(kp.dev, kp.key, 0);
0362 input_sync(kp.dev);
0363 }
0364
0365
0366 if (kfifo_len(&sony_laptop_input.fifo) != 0)
0367 mod_timer(&sony_laptop_input.release_key_timer,
0368 jiffies + msecs_to_jiffies(10));
0369
0370 spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
0371 }
0372
0373
0374 static void sony_laptop_report_input_event(u8 event)
0375 {
0376 struct input_dev *jog_dev = sony_laptop_input.jog_dev;
0377 struct input_dev *key_dev = sony_laptop_input.key_dev;
0378 struct sony_laptop_keypress kp = { NULL };
0379 int scancode = -1;
0380
0381 if (event == SONYPI_EVENT_FNKEY_RELEASED ||
0382 event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
0383
0384 return;
0385 }
0386
0387
0388 switch (event) {
0389
0390 case SONYPI_EVENT_JOGDIAL_UP:
0391 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
0392 input_report_rel(jog_dev, REL_WHEEL, 1);
0393 input_sync(jog_dev);
0394 return;
0395
0396 case SONYPI_EVENT_JOGDIAL_DOWN:
0397 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
0398 input_report_rel(jog_dev, REL_WHEEL, -1);
0399 input_sync(jog_dev);
0400 return;
0401
0402
0403 case SONYPI_EVENT_JOGDIAL_PRESSED:
0404 kp.key = BTN_MIDDLE;
0405 kp.dev = jog_dev;
0406 break;
0407
0408 default:
0409 if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
0410 dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
0411 break;
0412 }
0413 if ((scancode = sony_laptop_input_index[event]) != -1) {
0414 kp.key = sony_laptop_input_keycode_map[scancode];
0415 if (kp.key != KEY_UNKNOWN)
0416 kp.dev = key_dev;
0417 }
0418 break;
0419 }
0420
0421 if (kp.dev) {
0422
0423
0424 if (scancode != -1)
0425 input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
0426 input_report_key(kp.dev, kp.key, 1);
0427 input_sync(kp.dev);
0428
0429
0430 kfifo_in_locked(&sony_laptop_input.fifo,
0431 (unsigned char *)&kp, sizeof(kp),
0432 &sony_laptop_input.fifo_lock);
0433 mod_timer(&sony_laptop_input.release_key_timer,
0434 jiffies + msecs_to_jiffies(10));
0435 } else
0436 dprintk("unknown input event %.2x\n", event);
0437 }
0438
0439 static int sony_laptop_setup_input(struct acpi_device *acpi_device)
0440 {
0441 struct input_dev *jog_dev;
0442 struct input_dev *key_dev;
0443 int i;
0444 int error;
0445
0446
0447 if (atomic_add_return(1, &sony_laptop_input.users) > 1)
0448 return 0;
0449
0450
0451 spin_lock_init(&sony_laptop_input.fifo_lock);
0452 error = kfifo_alloc(&sony_laptop_input.fifo,
0453 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
0454 if (error) {
0455 pr_err("kfifo_alloc failed\n");
0456 goto err_dec_users;
0457 }
0458
0459 timer_setup(&sony_laptop_input.release_key_timer,
0460 do_sony_laptop_release_key, 0);
0461
0462
0463 key_dev = input_allocate_device();
0464 if (!key_dev) {
0465 error = -ENOMEM;
0466 goto err_free_kfifo;
0467 }
0468
0469 key_dev->name = "Sony Vaio Keys";
0470 key_dev->id.bustype = BUS_ISA;
0471 key_dev->id.vendor = PCI_VENDOR_ID_SONY;
0472 key_dev->dev.parent = &acpi_device->dev;
0473
0474
0475 input_set_capability(key_dev, EV_MSC, MSC_SCAN);
0476
0477 __set_bit(EV_KEY, key_dev->evbit);
0478 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
0479 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
0480 key_dev->keycode = &sony_laptop_input_keycode_map;
0481 for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
0482 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
0483 __clear_bit(KEY_RESERVED, key_dev->keybit);
0484
0485 error = input_register_device(key_dev);
0486 if (error)
0487 goto err_free_keydev;
0488
0489 sony_laptop_input.key_dev = key_dev;
0490
0491
0492 jog_dev = input_allocate_device();
0493 if (!jog_dev) {
0494 error = -ENOMEM;
0495 goto err_unregister_keydev;
0496 }
0497
0498 jog_dev->name = "Sony Vaio Jogdial";
0499 jog_dev->id.bustype = BUS_ISA;
0500 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
0501 jog_dev->dev.parent = &acpi_device->dev;
0502
0503 input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
0504 input_set_capability(jog_dev, EV_REL, REL_WHEEL);
0505
0506 error = input_register_device(jog_dev);
0507 if (error)
0508 goto err_free_jogdev;
0509
0510 sony_laptop_input.jog_dev = jog_dev;
0511
0512 return 0;
0513
0514 err_free_jogdev:
0515 input_free_device(jog_dev);
0516
0517 err_unregister_keydev:
0518 input_unregister_device(key_dev);
0519
0520 key_dev = NULL;
0521
0522 err_free_keydev:
0523 input_free_device(key_dev);
0524
0525 err_free_kfifo:
0526 kfifo_free(&sony_laptop_input.fifo);
0527
0528 err_dec_users:
0529 atomic_dec(&sony_laptop_input.users);
0530 return error;
0531 }
0532
0533 static void sony_laptop_remove_input(void)
0534 {
0535 struct sony_laptop_keypress kp = { NULL };
0536
0537
0538 if (!atomic_dec_and_test(&sony_laptop_input.users))
0539 return;
0540
0541 del_timer_sync(&sony_laptop_input.release_key_timer);
0542
0543
0544
0545
0546
0547 while (kfifo_out(&sony_laptop_input.fifo,
0548 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
0549 input_report_key(kp.dev, kp.key, 0);
0550 input_sync(kp.dev);
0551 }
0552
0553
0554 input_unregister_device(sony_laptop_input.key_dev);
0555 sony_laptop_input.key_dev = NULL;
0556
0557 if (sony_laptop_input.jog_dev) {
0558 input_unregister_device(sony_laptop_input.jog_dev);
0559 sony_laptop_input.jog_dev = NULL;
0560 }
0561
0562 kfifo_free(&sony_laptop_input.fifo);
0563 }
0564
0565
0566
0567 static atomic_t sony_pf_users = ATOMIC_INIT(0);
0568 static struct platform_driver sony_pf_driver = {
0569 .driver = {
0570 .name = "sony-laptop",
0571 }
0572 };
0573 static struct platform_device *sony_pf_device;
0574
0575 static int sony_pf_add(void)
0576 {
0577 int ret = 0;
0578
0579
0580 if (atomic_add_return(1, &sony_pf_users) > 1)
0581 return 0;
0582
0583 ret = platform_driver_register(&sony_pf_driver);
0584 if (ret)
0585 goto out;
0586
0587 sony_pf_device = platform_device_alloc("sony-laptop", -1);
0588 if (!sony_pf_device) {
0589 ret = -ENOMEM;
0590 goto out_platform_registered;
0591 }
0592
0593 ret = platform_device_add(sony_pf_device);
0594 if (ret)
0595 goto out_platform_alloced;
0596
0597 return 0;
0598
0599 out_platform_alloced:
0600 platform_device_put(sony_pf_device);
0601 sony_pf_device = NULL;
0602 out_platform_registered:
0603 platform_driver_unregister(&sony_pf_driver);
0604 out:
0605 atomic_dec(&sony_pf_users);
0606 return ret;
0607 }
0608
0609 static void sony_pf_remove(void)
0610 {
0611
0612 if (!atomic_dec_and_test(&sony_pf_users))
0613 return;
0614
0615 platform_device_unregister(sony_pf_device);
0616 platform_driver_unregister(&sony_pf_driver);
0617 }
0618
0619
0620
0621
0622
0623 #define SONY_MAX_BRIGHTNESS 8
0624
0625 #define SNC_VALIDATE_IN 0
0626 #define SNC_VALIDATE_OUT 1
0627
0628 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
0629 char *);
0630 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
0631 const char *, size_t);
0632 static int boolean_validate(const int, const int);
0633 static int brightness_default_validate(const int, const int);
0634
0635 struct sony_nc_value {
0636 char *name;
0637 char **acpiget;
0638 char **acpiset;
0639 int (*validate)(const int, const int);
0640 int value;
0641 int valid;
0642 int debug;
0643 struct device_attribute devattr;
0644 };
0645
0646 #define SNC_HANDLE_NAMES(_name, _values...) \
0647 static char *snc_##_name[] = { _values, NULL }
0648
0649 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
0650 { \
0651 .name = __stringify(_name), \
0652 .acpiget = _getters, \
0653 .acpiset = _setters, \
0654 .validate = _validate, \
0655 .debug = _debug, \
0656 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
0657 }
0658
0659 #define SNC_HANDLE_NULL { .name = NULL }
0660
0661 SNC_HANDLE_NAMES(fnkey_get, "GHKE");
0662
0663 SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
0664 SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
0665
0666 SNC_HANDLE_NAMES(cdpower_get, "GCDP");
0667 SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
0668
0669 SNC_HANDLE_NAMES(audiopower_get, "GAZP");
0670 SNC_HANDLE_NAMES(audiopower_set, "AZPW");
0671
0672 SNC_HANDLE_NAMES(lanpower_get, "GLNP");
0673 SNC_HANDLE_NAMES(lanpower_set, "LNPW");
0674
0675 SNC_HANDLE_NAMES(lidstate_get, "GLID");
0676
0677 SNC_HANDLE_NAMES(indicatorlamp_get, "GILS");
0678 SNC_HANDLE_NAMES(indicatorlamp_set, "SILS");
0679
0680 SNC_HANDLE_NAMES(gainbass_get, "GMGB");
0681 SNC_HANDLE_NAMES(gainbass_set, "CMGB");
0682
0683 SNC_HANDLE_NAMES(PID_get, "GPID");
0684
0685 SNC_HANDLE_NAMES(CTR_get, "GCTR");
0686 SNC_HANDLE_NAMES(CTR_set, "SCTR");
0687
0688 SNC_HANDLE_NAMES(PCR_get, "GPCR");
0689 SNC_HANDLE_NAMES(PCR_set, "SPCR");
0690
0691 SNC_HANDLE_NAMES(CMI_get, "GCMI");
0692 SNC_HANDLE_NAMES(CMI_set, "SCMI");
0693
0694 static struct sony_nc_value sony_nc_values[] = {
0695 SNC_HANDLE(brightness_default, snc_brightness_def_get,
0696 snc_brightness_def_set, brightness_default_validate, 0),
0697 SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
0698 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
0699 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
0700 boolean_validate, 0),
0701 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
0702 boolean_validate, 1),
0703 SNC_HANDLE(lidstate, snc_lidstate_get, NULL,
0704 boolean_validate, 0),
0705 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
0706 boolean_validate, 0),
0707 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
0708 boolean_validate, 0),
0709
0710 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
0711 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
0712 SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
0713 SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
0714 SNC_HANDLE_NULL
0715 };
0716
0717 static acpi_handle sony_nc_acpi_handle;
0718 static struct acpi_device *sony_nc_acpi_device = NULL;
0719
0720
0721
0722
0723
0724
0725 static union acpi_object *__call_snc_method(acpi_handle handle, char *method,
0726 u64 *value)
0727 {
0728 union acpi_object *result = NULL;
0729 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
0730 acpi_status status;
0731
0732 if (value) {
0733 struct acpi_object_list params;
0734 union acpi_object in;
0735 in.type = ACPI_TYPE_INTEGER;
0736 in.integer.value = *value;
0737 params.count = 1;
0738 params.pointer = ∈
0739 status = acpi_evaluate_object(handle, method, ¶ms, &output);
0740 dprintk("__call_snc_method: [%s:0x%.8x%.8x]\n", method,
0741 (unsigned int)(*value >> 32),
0742 (unsigned int)*value & 0xffffffff);
0743 } else {
0744 status = acpi_evaluate_object(handle, method, NULL, &output);
0745 dprintk("__call_snc_method: [%s]\n", method);
0746 }
0747
0748 if (ACPI_FAILURE(status)) {
0749 pr_err("Failed to evaluate [%s]\n", method);
0750 return NULL;
0751 }
0752
0753 result = (union acpi_object *) output.pointer;
0754 if (!result)
0755 dprintk("No return object [%s]\n", method);
0756
0757 return result;
0758 }
0759
0760 #define MIN(a, b) (a > b ? b : a)
0761 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
0762 void *buffer, size_t buflen)
0763 {
0764 int ret = 0;
0765 size_t len;
0766 union acpi_object *object = __call_snc_method(handle, name, value);
0767
0768 if (!object)
0769 return -EINVAL;
0770
0771 if (!buffer) {
0772
0773 } else if (object->type == ACPI_TYPE_BUFFER) {
0774 len = MIN(buflen, object->buffer.length);
0775 memset(buffer, 0, buflen);
0776 memcpy(buffer, object->buffer.pointer, len);
0777
0778 } else if (object->type == ACPI_TYPE_INTEGER) {
0779 len = MIN(buflen, sizeof(object->integer.value));
0780 memset(buffer, 0, buflen);
0781 memcpy(buffer, &object->integer.value, len);
0782
0783 } else {
0784 pr_warn("Unexpected acpi_object: 0x%x\n", object->type);
0785 ret = -EINVAL;
0786 }
0787
0788 kfree(object);
0789 return ret;
0790 }
0791
0792 static int sony_nc_int_call(acpi_handle handle, char *name, int *value, int
0793 *result)
0794 {
0795 int ret;
0796
0797 if (value) {
0798 u64 v = *value;
0799
0800 ret = sony_nc_buffer_call(handle, name, &v, result,
0801 sizeof(*result));
0802 } else {
0803 ret = sony_nc_buffer_call(handle, name, NULL, result,
0804 sizeof(*result));
0805 }
0806 return ret;
0807 }
0808
0809 struct sony_nc_handles {
0810 u16 cap[0x10];
0811 struct device_attribute devattr;
0812 };
0813
0814 static struct sony_nc_handles *handles;
0815
0816 static ssize_t sony_nc_handles_show(struct device *dev,
0817 struct device_attribute *attr, char *buffer)
0818 {
0819 ssize_t len = 0;
0820 int i;
0821
0822 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
0823 len += scnprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
0824 handles->cap[i]);
0825 }
0826 len += scnprintf(buffer + len, PAGE_SIZE - len, "\n");
0827
0828 return len;
0829 }
0830
0831 static int sony_nc_handles_setup(struct platform_device *pd)
0832 {
0833 int i, r, result, arg;
0834
0835 handles = kzalloc(sizeof(*handles), GFP_KERNEL);
0836 if (!handles)
0837 return -ENOMEM;
0838
0839 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
0840 arg = i + 0x20;
0841 r = sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg,
0842 &result);
0843 if (!r) {
0844 dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
0845 result, i);
0846 handles->cap[i] = result;
0847 }
0848 }
0849
0850 if (debug) {
0851 sysfs_attr_init(&handles->devattr.attr);
0852 handles->devattr.attr.name = "handles";
0853 handles->devattr.attr.mode = S_IRUGO;
0854 handles->devattr.show = sony_nc_handles_show;
0855
0856
0857 if (device_create_file(&pd->dev, &handles->devattr)) {
0858 kfree(handles);
0859 handles = NULL;
0860 return -1;
0861 }
0862 }
0863
0864 return 0;
0865 }
0866
0867 static int sony_nc_handles_cleanup(struct platform_device *pd)
0868 {
0869 if (handles) {
0870 if (debug)
0871 device_remove_file(&pd->dev, &handles->devattr);
0872 kfree(handles);
0873 handles = NULL;
0874 }
0875 return 0;
0876 }
0877
0878 static int sony_find_snc_handle(int handle)
0879 {
0880 int i;
0881
0882
0883 if (!handles || !handle)
0884 return -EINVAL;
0885
0886 for (i = 0; i < 0x10; i++) {
0887 if (handles->cap[i] == handle) {
0888 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
0889 handle, i);
0890 return i;
0891 }
0892 }
0893 dprintk("handle 0x%.4x not found\n", handle);
0894 return -EINVAL;
0895 }
0896
0897 static int sony_call_snc_handle(int handle, int argument, int *result)
0898 {
0899 int arg, ret = 0;
0900 int offset = sony_find_snc_handle(handle);
0901
0902 if (offset < 0)
0903 return offset;
0904
0905 arg = offset | argument;
0906 ret = sony_nc_int_call(sony_nc_acpi_handle, "SN07", &arg, result);
0907 dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result);
0908 return ret;
0909 }
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920 static int brightness_default_validate(const int direction, const int value)
0921 {
0922 switch (direction) {
0923 case SNC_VALIDATE_OUT:
0924 return value - 1;
0925 case SNC_VALIDATE_IN:
0926 if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
0927 return value + 1;
0928 }
0929 return -EINVAL;
0930 }
0931
0932
0933
0934
0935
0936
0937 static int boolean_validate(const int direction, const int value)
0938 {
0939 if (direction == SNC_VALIDATE_IN) {
0940 if (value != 0 && value != 1)
0941 return -EINVAL;
0942 }
0943 return value;
0944 }
0945
0946
0947
0948
0949 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
0950 char *buffer)
0951 {
0952 int value, ret = 0;
0953 struct sony_nc_value *item =
0954 container_of(attr, struct sony_nc_value, devattr);
0955
0956 if (!*item->acpiget)
0957 return -EIO;
0958
0959 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiget, NULL,
0960 &value);
0961 if (ret < 0)
0962 return -EIO;
0963
0964 if (item->validate)
0965 value = item->validate(SNC_VALIDATE_OUT, value);
0966
0967 return sysfs_emit(buffer, "%d\n", value);
0968 }
0969
0970 static ssize_t sony_nc_sysfs_store(struct device *dev,
0971 struct device_attribute *attr,
0972 const char *buffer, size_t count)
0973 {
0974 int value;
0975 int ret = 0;
0976 struct sony_nc_value *item =
0977 container_of(attr, struct sony_nc_value, devattr);
0978
0979 if (!item->acpiset)
0980 return -EIO;
0981
0982 if (count > 31)
0983 return -EINVAL;
0984
0985 if (kstrtoint(buffer, 10, &value))
0986 return -EINVAL;
0987
0988 if (item->validate)
0989 value = item->validate(SNC_VALIDATE_IN, value);
0990
0991 if (value < 0)
0992 return value;
0993
0994 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
0995 &value, NULL);
0996 if (ret < 0)
0997 return -EIO;
0998
0999 item->value = value;
1000 item->valid = 1;
1001 return count;
1002 }
1003
1004
1005
1006
1007
1008 struct sony_backlight_props {
1009 struct backlight_device *dev;
1010 int handle;
1011 int cmd_base;
1012 u8 offset;
1013 u8 maxlvl;
1014 };
1015 static struct sony_backlight_props sony_bl_props;
1016
1017 static int sony_backlight_update_status(struct backlight_device *bd)
1018 {
1019 int arg = bd->props.brightness + 1;
1020 return sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &arg, NULL);
1021 }
1022
1023 static int sony_backlight_get_brightness(struct backlight_device *bd)
1024 {
1025 int value;
1026
1027 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, &value))
1028 return 0;
1029
1030 return value - 1;
1031 }
1032
1033 static int sony_nc_get_brightness_ng(struct backlight_device *bd)
1034 {
1035 int result;
1036 struct sony_backlight_props *sdev =
1037 (struct sony_backlight_props *)bl_get_data(bd);
1038
1039 sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result);
1040
1041 return (result & 0xff) - sdev->offset;
1042 }
1043
1044 static int sony_nc_update_status_ng(struct backlight_device *bd)
1045 {
1046 int value, result;
1047 struct sony_backlight_props *sdev =
1048 (struct sony_backlight_props *)bl_get_data(bd);
1049
1050 value = bd->props.brightness + sdev->offset;
1051 if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10),
1052 &result))
1053 return -EIO;
1054
1055 return value;
1056 }
1057
1058 static const struct backlight_ops sony_backlight_ops = {
1059 .options = BL_CORE_SUSPENDRESUME,
1060 .update_status = sony_backlight_update_status,
1061 .get_brightness = sony_backlight_get_brightness,
1062 };
1063 static const struct backlight_ops sony_backlight_ng_ops = {
1064 .options = BL_CORE_SUSPENDRESUME,
1065 .update_status = sony_nc_update_status_ng,
1066 .get_brightness = sony_nc_get_brightness_ng,
1067 };
1068
1069
1070
1071
1072 struct sony_nc_event {
1073 u8 data;
1074 u8 event;
1075 };
1076
1077 static struct sony_nc_event sony_100_events[] = {
1078 { 0x90, SONYPI_EVENT_PKEY_P1 },
1079 { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
1080 { 0x91, SONYPI_EVENT_PKEY_P2 },
1081 { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
1082 { 0x81, SONYPI_EVENT_FNKEY_F1 },
1083 { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
1084 { 0x82, SONYPI_EVENT_FNKEY_F2 },
1085 { 0x02, SONYPI_EVENT_FNKEY_RELEASED },
1086 { 0x83, SONYPI_EVENT_FNKEY_F3 },
1087 { 0x03, SONYPI_EVENT_FNKEY_RELEASED },
1088 { 0x84, SONYPI_EVENT_FNKEY_F4 },
1089 { 0x04, SONYPI_EVENT_FNKEY_RELEASED },
1090 { 0x85, SONYPI_EVENT_FNKEY_F5 },
1091 { 0x05, SONYPI_EVENT_FNKEY_RELEASED },
1092 { 0x86, SONYPI_EVENT_FNKEY_F6 },
1093 { 0x06, SONYPI_EVENT_FNKEY_RELEASED },
1094 { 0x87, SONYPI_EVENT_FNKEY_F7 },
1095 { 0x07, SONYPI_EVENT_FNKEY_RELEASED },
1096 { 0x88, SONYPI_EVENT_FNKEY_F8 },
1097 { 0x08, SONYPI_EVENT_FNKEY_RELEASED },
1098 { 0x89, SONYPI_EVENT_FNKEY_F9 },
1099 { 0x09, SONYPI_EVENT_FNKEY_RELEASED },
1100 { 0x8A, SONYPI_EVENT_FNKEY_F10 },
1101 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
1102 { 0x8B, SONYPI_EVENT_FNKEY_F11 },
1103 { 0x0B, SONYPI_EVENT_FNKEY_RELEASED },
1104 { 0x8C, SONYPI_EVENT_FNKEY_F12 },
1105 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1106 { 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1107 { 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
1108 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
1109 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
1110 { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
1111 { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
1112 { 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED },
1113 { 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED },
1114 { 0xa5, SONYPI_EVENT_VENDOR_PRESSED },
1115 { 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED },
1116 { 0xa6, SONYPI_EVENT_HELP_PRESSED },
1117 { 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED },
1118 { 0xa8, SONYPI_EVENT_FNKEY_1 },
1119 { 0x28, SONYPI_EVENT_ANYBUTTON_RELEASED },
1120 { 0, 0 },
1121 };
1122
1123 static struct sony_nc_event sony_127_events[] = {
1124 { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
1125 { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
1126 { 0x82, SONYPI_EVENT_PKEY_P1 },
1127 { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
1128 { 0x83, SONYPI_EVENT_PKEY_P2 },
1129 { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
1130 { 0x84, SONYPI_EVENT_PKEY_P3 },
1131 { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
1132 { 0x85, SONYPI_EVENT_PKEY_P4 },
1133 { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
1134 { 0x86, SONYPI_EVENT_PKEY_P5 },
1135 { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
1136 { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
1137 { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
1138 { 0, 0 },
1139 };
1140
1141 static int sony_nc_hotkeys_decode(u32 event, unsigned int handle)
1142 {
1143 int ret = -EINVAL;
1144 unsigned int result = 0;
1145 struct sony_nc_event *key_event;
1146
1147 if (sony_call_snc_handle(handle, 0x200, &result)) {
1148 dprintk("Unable to decode event 0x%.2x 0x%.2x\n", handle,
1149 event);
1150 return -EINVAL;
1151 }
1152
1153 result &= 0xFF;
1154
1155 if (handle == 0x0100)
1156 key_event = sony_100_events;
1157 else
1158 key_event = sony_127_events;
1159
1160 for (; key_event->data; key_event++) {
1161 if (key_event->data == result) {
1162 ret = key_event->event;
1163 break;
1164 }
1165 }
1166
1167 if (!key_event->data)
1168 pr_info("Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n",
1169 event, result, handle);
1170
1171 return ret;
1172 }
1173
1174
1175
1176
1177 enum event_types {
1178 HOTKEY = 1,
1179 KILLSWITCH,
1180 GFX_SWITCH
1181 };
1182 static void sony_nc_notify(struct acpi_device *device, u32 event)
1183 {
1184 u32 real_ev = event;
1185 u8 ev_type = 0;
1186 int ret;
1187
1188 dprintk("sony_nc_notify, event: 0x%.2x\n", event);
1189
1190 if (event >= 0x90) {
1191 unsigned int result = 0;
1192 unsigned int arg = 0;
1193 unsigned int handle = 0;
1194 unsigned int offset = event - 0x90;
1195
1196 if (offset >= ARRAY_SIZE(handles->cap)) {
1197 pr_err("Event 0x%x outside of capabilities list\n",
1198 event);
1199 return;
1200 }
1201 handle = handles->cap[offset];
1202
1203
1204 switch (handle) {
1205
1206 case 0x0100:
1207 case 0x0127:
1208 ev_type = HOTKEY;
1209 ret = sony_nc_hotkeys_decode(event, handle);
1210
1211 if (ret > 0) {
1212 sony_laptop_report_input_event(ret);
1213 real_ev = ret;
1214 }
1215
1216 break;
1217
1218
1219 case 0x0124:
1220 case 0x0135:
1221
1222
1223
1224
1225
1226
1227 ev_type = KILLSWITCH;
1228 sony_call_snc_handle(handle, 0x0100, &result);
1229 real_ev = result & 0x03;
1230
1231
1232 if (real_ev == 1)
1233 sony_nc_rfkill_update();
1234
1235 break;
1236
1237 case 0x0128:
1238 case 0x0146:
1239
1240 sony_call_snc_handle(handle, 0x0000, &result);
1241 dprintk("GFX switch event received (reason: %s)\n",
1242 (result == 0x1) ? "switch change" :
1243 (result == 0x2) ? "output switch" :
1244 (result == 0x3) ? "output switch" :
1245 "");
1246
1247 ev_type = GFX_SWITCH;
1248 real_ev = __sony_nc_gfx_switch_status_get();
1249 break;
1250
1251 case 0x015B:
1252
1253 ev_type = GFX_SWITCH;
1254 real_ev = __sony_nc_gfx_switch_status_get();
1255 break;
1256 default:
1257 dprintk("Unknown event 0x%x for handle 0x%x\n",
1258 event, handle);
1259 break;
1260 }
1261
1262
1263 arg = 1 << offset;
1264 sony_nc_int_call(sony_nc_acpi_handle, "SN05", &arg, &result);
1265
1266 } else {
1267
1268 ev_type = HOTKEY;
1269 sony_laptop_report_input_event(real_ev);
1270 }
1271 acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class,
1272 dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev);
1273 }
1274
1275 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
1276 void *context, void **return_value)
1277 {
1278 struct acpi_device_info *info;
1279
1280 if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
1281 pr_warn("method: name: %4.4s, args %X\n",
1282 (char *)&info->name, info->param_count);
1283
1284 kfree(info);
1285 }
1286
1287 return AE_OK;
1288 }
1289
1290
1291
1292
1293 static void sony_nc_function_setup(struct acpi_device *device,
1294 struct platform_device *pf_device)
1295 {
1296 unsigned int i, result, bitmask, arg;
1297
1298 if (!handles)
1299 return;
1300
1301
1302 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1303 unsigned int handle = handles->cap[i];
1304
1305 if (!handle)
1306 continue;
1307
1308 dprintk("setting up handle 0x%.4x\n", handle);
1309
1310 switch (handle) {
1311 case 0x0100:
1312 case 0x0101:
1313 case 0x0127:
1314
1315 sony_call_snc_handle(handle, 0, &result);
1316 break;
1317 case 0x0102:
1318
1319 sony_call_snc_handle(handle, 0x100, &result);
1320 break;
1321 case 0x0105:
1322 case 0x0148:
1323
1324 result = sony_nc_touchpad_setup(pf_device, handle);
1325 if (result)
1326 pr_err("couldn't set up touchpad control function (%d)\n",
1327 result);
1328 break;
1329 case 0x0115:
1330 case 0x0136:
1331 case 0x013f:
1332 result = sony_nc_battery_care_setup(pf_device, handle);
1333 if (result)
1334 pr_err("couldn't set up battery care function (%d)\n",
1335 result);
1336 break;
1337 case 0x0119:
1338 case 0x015D:
1339 result = sony_nc_lid_resume_setup(pf_device, handle);
1340 if (result)
1341 pr_err("couldn't set up lid resume function (%d)\n",
1342 result);
1343 break;
1344 case 0x0122:
1345 result = sony_nc_thermal_setup(pf_device);
1346 if (result)
1347 pr_err("couldn't set up thermal profile function (%d)\n",
1348 result);
1349 break;
1350 case 0x0128:
1351 case 0x0146:
1352 case 0x015B:
1353 result = sony_nc_gfx_switch_setup(pf_device, handle);
1354 if (result)
1355 pr_err("couldn't set up GFX Switch status (%d)\n",
1356 result);
1357 break;
1358 case 0x0131:
1359 result = sony_nc_highspeed_charging_setup(pf_device);
1360 if (result)
1361 pr_err("couldn't set up high speed charging function (%d)\n",
1362 result);
1363 break;
1364 case 0x0124:
1365 case 0x0135:
1366 result = sony_nc_rfkill_setup(device, handle);
1367 if (result)
1368 pr_err("couldn't set up rfkill support (%d)\n",
1369 result);
1370 break;
1371 case 0x0137:
1372 case 0x0143:
1373 case 0x014b:
1374 case 0x014c:
1375 case 0x0153:
1376 case 0x0163:
1377 result = sony_nc_kbd_backlight_setup(pf_device, handle);
1378 if (result)
1379 pr_err("couldn't set up keyboard backlight function (%d)\n",
1380 result);
1381 break;
1382 case 0x0121:
1383 result = sony_nc_lowbatt_setup(pf_device);
1384 if (result)
1385 pr_err("couldn't set up low battery function (%d)\n",
1386 result);
1387 break;
1388 case 0x0149:
1389 result = sony_nc_fanspeed_setup(pf_device);
1390 if (result)
1391 pr_err("couldn't set up fan speed function (%d)\n",
1392 result);
1393 break;
1394 case 0x0155:
1395 result = sony_nc_usb_charge_setup(pf_device);
1396 if (result)
1397 pr_err("couldn't set up USB charge support (%d)\n",
1398 result);
1399 break;
1400 case 0x011D:
1401 result = sony_nc_panelid_setup(pf_device);
1402 if (result)
1403 pr_err("couldn't set up panel ID function (%d)\n",
1404 result);
1405 break;
1406 case 0x0168:
1407 result = sony_nc_smart_conn_setup(pf_device);
1408 if (result)
1409 pr_err("couldn't set up smart connect support (%d)\n",
1410 result);
1411 break;
1412 default:
1413 continue;
1414 }
1415 }
1416
1417
1418 arg = 0x10;
1419 if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask))
1420 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask,
1421 &result);
1422 }
1423
1424 static void sony_nc_function_cleanup(struct platform_device *pd)
1425 {
1426 unsigned int i, result, bitmask, handle;
1427
1428 if (!handles)
1429 return;
1430
1431
1432 sony_nc_int_call(sony_nc_acpi_handle, "SN01", NULL, &bitmask);
1433 sony_nc_int_call(sony_nc_acpi_handle, "SN03", &bitmask, &result);
1434
1435
1436 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1437
1438 handle = handles->cap[i];
1439
1440 if (!handle)
1441 continue;
1442
1443 switch (handle) {
1444 case 0x0105:
1445 case 0x0148:
1446 sony_nc_touchpad_cleanup(pd);
1447 break;
1448 case 0x0115:
1449 case 0x0136:
1450 case 0x013f:
1451 sony_nc_battery_care_cleanup(pd);
1452 break;
1453 case 0x0119:
1454 case 0x015D:
1455 sony_nc_lid_resume_cleanup(pd);
1456 break;
1457 case 0x0122:
1458 sony_nc_thermal_cleanup(pd);
1459 break;
1460 case 0x0128:
1461 case 0x0146:
1462 case 0x015B:
1463 sony_nc_gfx_switch_cleanup(pd);
1464 break;
1465 case 0x0131:
1466 sony_nc_highspeed_charging_cleanup(pd);
1467 break;
1468 case 0x0124:
1469 case 0x0135:
1470 sony_nc_rfkill_cleanup();
1471 break;
1472 case 0x0137:
1473 case 0x0143:
1474 case 0x014b:
1475 case 0x014c:
1476 case 0x0153:
1477 case 0x0163:
1478 sony_nc_kbd_backlight_cleanup(pd, handle);
1479 break;
1480 case 0x0121:
1481 sony_nc_lowbatt_cleanup(pd);
1482 break;
1483 case 0x0149:
1484 sony_nc_fanspeed_cleanup(pd);
1485 break;
1486 case 0x0155:
1487 sony_nc_usb_charge_cleanup(pd);
1488 break;
1489 case 0x011D:
1490 sony_nc_panelid_cleanup(pd);
1491 break;
1492 case 0x0168:
1493 sony_nc_smart_conn_cleanup(pd);
1494 break;
1495 default:
1496 continue;
1497 }
1498 }
1499
1500
1501 sony_nc_handles_cleanup(pd);
1502 }
1503
1504 #ifdef CONFIG_PM_SLEEP
1505 static void sony_nc_function_resume(void)
1506 {
1507 unsigned int i, result, bitmask, arg;
1508
1509 dprintk("Resuming SNC device\n");
1510
1511 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1512 unsigned int handle = handles->cap[i];
1513
1514 if (!handle)
1515 continue;
1516
1517 switch (handle) {
1518 case 0x0100:
1519 case 0x0101:
1520 case 0x0127:
1521
1522 sony_call_snc_handle(handle, 0, &result);
1523 break;
1524 case 0x0102:
1525
1526 sony_call_snc_handle(handle, 0x100, &result);
1527 break;
1528 case 0x0122:
1529 sony_nc_thermal_resume();
1530 break;
1531 case 0x0124:
1532 case 0x0135:
1533 sony_nc_rfkill_update();
1534 break;
1535 default:
1536 continue;
1537 }
1538 }
1539
1540
1541 arg = 0x10;
1542 if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask))
1543 sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask,
1544 &result);
1545 }
1546
1547 static int sony_nc_resume(struct device *dev)
1548 {
1549 struct sony_nc_value *item;
1550
1551 for (item = sony_nc_values; item->name; item++) {
1552 int ret;
1553
1554 if (!item->valid)
1555 continue;
1556 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
1557 &item->value, NULL);
1558 if (ret < 0) {
1559 pr_err("%s: %d\n", __func__, ret);
1560 break;
1561 }
1562 }
1563
1564 if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
1565 int arg = 1;
1566 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
1567 dprintk("ECON Method failed\n");
1568 }
1569
1570 if (acpi_has_method(sony_nc_acpi_handle, "SN00"))
1571 sony_nc_function_resume();
1572
1573 return 0;
1574 }
1575 #endif
1576
1577 static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
1578
1579 static void sony_nc_rfkill_cleanup(void)
1580 {
1581 int i;
1582
1583 for (i = 0; i < N_SONY_RFKILL; i++) {
1584 if (sony_rfkill_devices[i]) {
1585 rfkill_unregister(sony_rfkill_devices[i]);
1586 rfkill_destroy(sony_rfkill_devices[i]);
1587 }
1588 }
1589 }
1590
1591 static int sony_nc_rfkill_set(void *data, bool blocked)
1592 {
1593 int result;
1594 int argument = sony_rfkill_address[(long) data] + 0x100;
1595
1596 if (!blocked)
1597 argument |= 0x070000;
1598
1599 return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1600 }
1601
1602 static const struct rfkill_ops sony_rfkill_ops = {
1603 .set_block = sony_nc_rfkill_set,
1604 };
1605
1606 static int sony_nc_setup_rfkill(struct acpi_device *device,
1607 enum sony_nc_rfkill nc_type)
1608 {
1609 int err;
1610 struct rfkill *rfk;
1611 enum rfkill_type type;
1612 const char *name;
1613 int result;
1614 bool hwblock, swblock;
1615
1616 switch (nc_type) {
1617 case SONY_WIFI:
1618 type = RFKILL_TYPE_WLAN;
1619 name = "sony-wifi";
1620 break;
1621 case SONY_BLUETOOTH:
1622 type = RFKILL_TYPE_BLUETOOTH;
1623 name = "sony-bluetooth";
1624 break;
1625 case SONY_WWAN:
1626 type = RFKILL_TYPE_WWAN;
1627 name = "sony-wwan";
1628 break;
1629 case SONY_WIMAX:
1630 type = RFKILL_TYPE_WIMAX;
1631 name = "sony-wimax";
1632 break;
1633 default:
1634 return -EINVAL;
1635 }
1636
1637 rfk = rfkill_alloc(name, &device->dev, type,
1638 &sony_rfkill_ops, (void *)nc_type);
1639 if (!rfk)
1640 return -ENOMEM;
1641
1642 err = sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1643 if (err < 0) {
1644 rfkill_destroy(rfk);
1645 return err;
1646 }
1647 hwblock = !(result & 0x1);
1648
1649 err = sony_call_snc_handle(sony_rfkill_handle,
1650 sony_rfkill_address[nc_type],
1651 &result);
1652 if (err < 0) {
1653 rfkill_destroy(rfk);
1654 return err;
1655 }
1656 swblock = !(result & 0x2);
1657
1658 rfkill_init_sw_state(rfk, swblock);
1659 rfkill_set_hw_state(rfk, hwblock);
1660
1661 err = rfkill_register(rfk);
1662 if (err) {
1663 rfkill_destroy(rfk);
1664 return err;
1665 }
1666 sony_rfkill_devices[nc_type] = rfk;
1667 return err;
1668 }
1669
1670 static void sony_nc_rfkill_update(void)
1671 {
1672 enum sony_nc_rfkill i;
1673 int result;
1674 bool hwblock;
1675
1676 sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1677 hwblock = !(result & 0x1);
1678
1679 for (i = 0; i < N_SONY_RFKILL; i++) {
1680 int argument = sony_rfkill_address[i];
1681
1682 if (!sony_rfkill_devices[i])
1683 continue;
1684
1685 if (hwblock) {
1686 if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1687
1688 }
1689 continue;
1690 }
1691
1692 sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1693 rfkill_set_states(sony_rfkill_devices[i],
1694 !(result & 0x2), false);
1695 }
1696 }
1697
1698 static int sony_nc_rfkill_setup(struct acpi_device *device,
1699 unsigned int handle)
1700 {
1701 u64 offset;
1702 int i;
1703 unsigned char buffer[32] = { 0 };
1704
1705 offset = sony_find_snc_handle(handle);
1706 sony_rfkill_handle = handle;
1707
1708 i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
1709 32);
1710 if (i < 0)
1711 return i;
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732 for (i = 0; i < ARRAY_SIZE(buffer); i++) {
1733
1734 if (buffer[i] == 0xff)
1735 break;
1736
1737 dprintk("Radio devices, found 0x%.2x\n", buffer[i]);
1738
1739 if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI])
1740 sony_nc_setup_rfkill(device, SONY_WIFI);
1741
1742 if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1743 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1744
1745 if (((0xf0 & buffer[i]) == 0x20 ||
1746 (0xf0 & buffer[i]) == 0x50) &&
1747 !sony_rfkill_devices[SONY_WWAN])
1748 sony_nc_setup_rfkill(device, SONY_WWAN);
1749
1750 if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1751 sony_nc_setup_rfkill(device, SONY_WIMAX);
1752 }
1753 return 0;
1754 }
1755
1756
1757 struct kbd_backlight {
1758 unsigned int handle;
1759 unsigned int base;
1760 unsigned int mode;
1761 unsigned int timeout;
1762 unsigned int has_timeout;
1763 struct device_attribute mode_attr;
1764 struct device_attribute timeout_attr;
1765 };
1766
1767 static struct kbd_backlight *kbdbl_ctl;
1768
1769 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1770 {
1771 int result;
1772
1773 if (value > 2)
1774 return -EINVAL;
1775
1776 if (sony_call_snc_handle(kbdbl_ctl->handle,
1777 (value << 0x10) | (kbdbl_ctl->base), &result))
1778 return -EIO;
1779
1780
1781 if (value != 1)
1782 sony_call_snc_handle(kbdbl_ctl->handle,
1783 (value << 0x0f) | (kbdbl_ctl->base + 0x100),
1784 &result);
1785
1786 kbdbl_ctl->mode = value;
1787
1788 return 0;
1789 }
1790
1791 static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
1792 struct device_attribute *attr,
1793 const char *buffer, size_t count)
1794 {
1795 int ret = 0;
1796 unsigned long value;
1797
1798 if (count > 31)
1799 return -EINVAL;
1800
1801 if (kstrtoul(buffer, 10, &value))
1802 return -EINVAL;
1803
1804 ret = __sony_nc_kbd_backlight_mode_set(value);
1805 if (ret < 0)
1806 return ret;
1807
1808 return count;
1809 }
1810
1811 static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
1812 struct device_attribute *attr, char *buffer)
1813 {
1814 return sysfs_emit(buffer, "%d\n", kbdbl_ctl->mode);
1815 }
1816
1817 static int __sony_nc_kbd_backlight_timeout_set(u8 value)
1818 {
1819 int result;
1820
1821 if (value > 3)
1822 return -EINVAL;
1823
1824 if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) |
1825 (kbdbl_ctl->base + 0x200), &result))
1826 return -EIO;
1827
1828 kbdbl_ctl->timeout = value;
1829
1830 return 0;
1831 }
1832
1833 static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
1834 struct device_attribute *attr,
1835 const char *buffer, size_t count)
1836 {
1837 int ret = 0;
1838 unsigned long value;
1839
1840 if (count > 31)
1841 return -EINVAL;
1842
1843 if (kstrtoul(buffer, 10, &value))
1844 return -EINVAL;
1845
1846 ret = __sony_nc_kbd_backlight_timeout_set(value);
1847 if (ret < 0)
1848 return ret;
1849
1850 return count;
1851 }
1852
1853 static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
1854 struct device_attribute *attr, char *buffer)
1855 {
1856 return sysfs_emit(buffer, "%d\n", kbdbl_ctl->timeout);
1857 }
1858
1859 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
1860 unsigned int handle)
1861 {
1862 int result;
1863 int probe_base = 0;
1864 int ctl_base = 0;
1865 int ret = 0;
1866
1867 if (kbdbl_ctl) {
1868 pr_warn("handle 0x%.4x: keyboard backlight setup already done for 0x%.4x\n",
1869 handle, kbdbl_ctl->handle);
1870 return -EBUSY;
1871 }
1872
1873
1874
1875
1876 switch (handle) {
1877 case 0x0153:
1878 probe_base = 0x0;
1879 ctl_base = 0x0;
1880 break;
1881 case 0x0137:
1882 probe_base = 0x0B00;
1883 ctl_base = 0x0C00;
1884 break;
1885 default:
1886 probe_base = 0x0100;
1887 ctl_base = 0x4000;
1888 break;
1889 }
1890
1891 ret = sony_call_snc_handle(handle, probe_base, &result);
1892 if (ret)
1893 return ret;
1894
1895 if ((handle == 0x0137 && !(result & 0x02)) ||
1896 !(result & 0x01)) {
1897 dprintk("no backlight keyboard found\n");
1898 return 0;
1899 }
1900
1901 kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
1902 if (!kbdbl_ctl)
1903 return -ENOMEM;
1904
1905 kbdbl_ctl->mode = kbd_backlight;
1906 kbdbl_ctl->timeout = kbd_backlight_timeout;
1907 kbdbl_ctl->handle = handle;
1908 kbdbl_ctl->base = ctl_base;
1909
1910 kbdbl_ctl->has_timeout = handle != 0x0153;
1911
1912 sysfs_attr_init(&kbdbl_ctl->mode_attr.attr);
1913 kbdbl_ctl->mode_attr.attr.name = "kbd_backlight";
1914 kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1915 kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1916 kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1917
1918 ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr);
1919 if (ret)
1920 goto outkzalloc;
1921
1922 __sony_nc_kbd_backlight_mode_set(kbdbl_ctl->mode);
1923
1924 if (kbdbl_ctl->has_timeout) {
1925 sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr);
1926 kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout";
1927 kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1928 kbdbl_ctl->timeout_attr.show =
1929 sony_nc_kbd_backlight_timeout_show;
1930 kbdbl_ctl->timeout_attr.store =
1931 sony_nc_kbd_backlight_timeout_store;
1932
1933 ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1934 if (ret)
1935 goto outmode;
1936
1937 __sony_nc_kbd_backlight_timeout_set(kbdbl_ctl->timeout);
1938 }
1939
1940
1941 return 0;
1942
1943 outmode:
1944 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1945 outkzalloc:
1946 kfree(kbdbl_ctl);
1947 kbdbl_ctl = NULL;
1948 return ret;
1949 }
1950
1951 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd,
1952 unsigned int handle)
1953 {
1954 if (kbdbl_ctl && handle == kbdbl_ctl->handle) {
1955 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1956 if (kbdbl_ctl->has_timeout)
1957 device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
1958 kfree(kbdbl_ctl);
1959 kbdbl_ctl = NULL;
1960 }
1961 }
1962
1963 struct battery_care_control {
1964 struct device_attribute attrs[2];
1965 unsigned int handle;
1966 };
1967 static struct battery_care_control *bcare_ctl;
1968
1969 static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
1970 struct device_attribute *attr,
1971 const char *buffer, size_t count)
1972 {
1973 unsigned int result, cmd;
1974 unsigned long value;
1975
1976 if (count > 31)
1977 return -EINVAL;
1978
1979 if (kstrtoul(buffer, 10, &value))
1980 return -EINVAL;
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994 cmd = 0;
1995
1996 if (value > 0) {
1997 if (value <= 50)
1998 cmd = 0x20;
1999
2000 else if (value <= 80)
2001 cmd = 0x10;
2002
2003 else if (value <= 100)
2004 cmd = 0x30;
2005
2006 else
2007 return -EINVAL;
2008
2009
2010
2011
2012
2013
2014 if (bcare_ctl->handle != 0x013f)
2015 cmd = cmd | (cmd << 2);
2016
2017 cmd = (cmd | 0x1) << 0x10;
2018 }
2019
2020 if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
2021 return -EIO;
2022
2023 return count;
2024 }
2025
2026 static ssize_t sony_nc_battery_care_limit_show(struct device *dev,
2027 struct device_attribute *attr, char *buffer)
2028 {
2029 unsigned int result, status;
2030
2031 if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result))
2032 return -EIO;
2033
2034 status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0;
2035 switch (status) {
2036 case 1:
2037 status = 80;
2038 break;
2039 case 2:
2040 status = 50;
2041 break;
2042 case 3:
2043 status = 100;
2044 break;
2045 default:
2046 status = 0;
2047 break;
2048 }
2049
2050 return sysfs_emit(buffer, "%d\n", status);
2051 }
2052
2053 static ssize_t sony_nc_battery_care_health_show(struct device *dev,
2054 struct device_attribute *attr, char *buffer)
2055 {
2056 unsigned int health;
2057
2058 if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health))
2059 return -EIO;
2060
2061 return sysfs_emit(buffer, "%d\n", health & 0xff);
2062 }
2063
2064 static int sony_nc_battery_care_setup(struct platform_device *pd,
2065 unsigned int handle)
2066 {
2067 int ret = 0;
2068
2069 bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL);
2070 if (!bcare_ctl)
2071 return -ENOMEM;
2072
2073 bcare_ctl->handle = handle;
2074
2075 sysfs_attr_init(&bcare_ctl->attrs[0].attr);
2076 bcare_ctl->attrs[0].attr.name = "battery_care_limiter";
2077 bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2078 bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show;
2079 bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store;
2080
2081 ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]);
2082 if (ret)
2083 goto outkzalloc;
2084
2085
2086 if (handle == 0x0115)
2087 return 0;
2088
2089 sysfs_attr_init(&bcare_ctl->attrs[1].attr);
2090 bcare_ctl->attrs[1].attr.name = "battery_care_health";
2091 bcare_ctl->attrs[1].attr.mode = S_IRUGO;
2092 bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show;
2093
2094 ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]);
2095 if (ret)
2096 goto outlimiter;
2097
2098 return 0;
2099
2100 outlimiter:
2101 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2102
2103 outkzalloc:
2104 kfree(bcare_ctl);
2105 bcare_ctl = NULL;
2106
2107 return ret;
2108 }
2109
2110 static void sony_nc_battery_care_cleanup(struct platform_device *pd)
2111 {
2112 if (bcare_ctl) {
2113 device_remove_file(&pd->dev, &bcare_ctl->attrs[0]);
2114 if (bcare_ctl->handle != 0x0115)
2115 device_remove_file(&pd->dev, &bcare_ctl->attrs[1]);
2116
2117 kfree(bcare_ctl);
2118 bcare_ctl = NULL;
2119 }
2120 }
2121
2122 struct snc_thermal_ctrl {
2123 unsigned int mode;
2124 unsigned int profiles;
2125 struct device_attribute mode_attr;
2126 struct device_attribute profiles_attr;
2127 };
2128 static struct snc_thermal_ctrl *th_handle;
2129
2130 #define THM_PROFILE_MAX 3
2131 static const char * const snc_thermal_profiles[] = {
2132 "balanced",
2133 "silent",
2134 "performance"
2135 };
2136
2137 static int sony_nc_thermal_mode_set(unsigned short mode)
2138 {
2139 unsigned int result;
2140
2141
2142
2143
2144
2145
2146
2147 if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX)
2148 return -EINVAL;
2149
2150 if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result))
2151 return -EIO;
2152
2153 th_handle->mode = mode;
2154
2155 return 0;
2156 }
2157
2158 static int sony_nc_thermal_mode_get(void)
2159 {
2160 unsigned int result;
2161
2162 if (sony_call_snc_handle(0x0122, 0x0100, &result))
2163 return -EIO;
2164
2165 return result & 0xff;
2166 }
2167
2168 static ssize_t sony_nc_thermal_profiles_show(struct device *dev,
2169 struct device_attribute *attr, char *buffer)
2170 {
2171 short cnt;
2172 size_t idx = 0;
2173
2174 for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) {
2175 if (!cnt || (th_handle->profiles & cnt))
2176 idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "%s ",
2177 snc_thermal_profiles[cnt]);
2178 }
2179 idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "\n");
2180
2181 return idx;
2182 }
2183
2184 static ssize_t sony_nc_thermal_mode_store(struct device *dev,
2185 struct device_attribute *attr,
2186 const char *buffer, size_t count)
2187 {
2188 unsigned short cmd;
2189 size_t len = count;
2190
2191 if (count == 0)
2192 return -EINVAL;
2193
2194
2195 if (buffer[len - 1] == '\n')
2196 len--;
2197
2198 for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++)
2199 if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0)
2200 break;
2201
2202 if (sony_nc_thermal_mode_set(cmd))
2203 return -EIO;
2204
2205 return count;
2206 }
2207
2208 static ssize_t sony_nc_thermal_mode_show(struct device *dev,
2209 struct device_attribute *attr, char *buffer)
2210 {
2211 int mode = sony_nc_thermal_mode_get();
2212
2213 if (mode < 0)
2214 return mode;
2215
2216 return sysfs_emit(buffer, "%s\n", snc_thermal_profiles[mode]);
2217 }
2218
2219 static int sony_nc_thermal_setup(struct platform_device *pd)
2220 {
2221 int ret = 0;
2222 th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL);
2223 if (!th_handle)
2224 return -ENOMEM;
2225
2226 ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles);
2227 if (ret) {
2228 pr_warn("couldn't to read the thermal profiles\n");
2229 goto outkzalloc;
2230 }
2231
2232 ret = sony_nc_thermal_mode_get();
2233 if (ret < 0) {
2234 pr_warn("couldn't to read the current thermal profile");
2235 goto outkzalloc;
2236 }
2237 th_handle->mode = ret;
2238
2239 sysfs_attr_init(&th_handle->profiles_attr.attr);
2240 th_handle->profiles_attr.attr.name = "thermal_profiles";
2241 th_handle->profiles_attr.attr.mode = S_IRUGO;
2242 th_handle->profiles_attr.show = sony_nc_thermal_profiles_show;
2243
2244 sysfs_attr_init(&th_handle->mode_attr.attr);
2245 th_handle->mode_attr.attr.name = "thermal_control";
2246 th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
2247 th_handle->mode_attr.show = sony_nc_thermal_mode_show;
2248 th_handle->mode_attr.store = sony_nc_thermal_mode_store;
2249
2250 ret = device_create_file(&pd->dev, &th_handle->profiles_attr);
2251 if (ret)
2252 goto outkzalloc;
2253
2254 ret = device_create_file(&pd->dev, &th_handle->mode_attr);
2255 if (ret)
2256 goto outprofiles;
2257
2258 return 0;
2259
2260 outprofiles:
2261 device_remove_file(&pd->dev, &th_handle->profiles_attr);
2262 outkzalloc:
2263 kfree(th_handle);
2264 th_handle = NULL;
2265 return ret;
2266 }
2267
2268 static void sony_nc_thermal_cleanup(struct platform_device *pd)
2269 {
2270 if (th_handle) {
2271 device_remove_file(&pd->dev, &th_handle->profiles_attr);
2272 device_remove_file(&pd->dev, &th_handle->mode_attr);
2273 kfree(th_handle);
2274 th_handle = NULL;
2275 }
2276 }
2277
2278 #ifdef CONFIG_PM_SLEEP
2279 static void sony_nc_thermal_resume(void)
2280 {
2281 int status;
2282
2283 if (!th_handle)
2284 return;
2285
2286 status = sony_nc_thermal_mode_get();
2287
2288 if (status != th_handle->mode)
2289 sony_nc_thermal_mode_set(th_handle->mode);
2290 }
2291 #endif
2292
2293
2294 #define LID_RESUME_S5 0
2295 #define LID_RESUME_S4 1
2296 #define LID_RESUME_S3 2
2297 #define LID_RESUME_MAX 3
2298 struct snc_lid_resume_control {
2299 struct device_attribute attrs[LID_RESUME_MAX];
2300 unsigned int status;
2301 int handle;
2302 };
2303 static struct snc_lid_resume_control *lid_ctl;
2304
2305 static ssize_t sony_nc_lid_resume_store(struct device *dev,
2306 struct device_attribute *attr,
2307 const char *buffer, size_t count)
2308 {
2309 unsigned int result;
2310 unsigned long value;
2311 unsigned int pos = LID_RESUME_S5;
2312 if (count > 31)
2313 return -EINVAL;
2314
2315 if (kstrtoul(buffer, 10, &value) || value > 1)
2316 return -EINVAL;
2317
2318
2319
2320
2321
2322
2323
2324 while (pos < LID_RESUME_MAX) {
2325 if (&lid_ctl->attrs[pos].attr == &attr->attr)
2326 break;
2327 pos++;
2328 }
2329 if (pos == LID_RESUME_MAX)
2330 return -EINVAL;
2331
2332 if (value)
2333 value = lid_ctl->status | (1 << pos);
2334 else
2335 value = lid_ctl->status & ~(1 << pos);
2336
2337 if (sony_call_snc_handle(lid_ctl->handle, value << 0x10 | 0x0100,
2338 &result))
2339 return -EIO;
2340
2341 lid_ctl->status = value;
2342
2343 return count;
2344 }
2345
2346 static ssize_t sony_nc_lid_resume_show(struct device *dev,
2347 struct device_attribute *attr,
2348 char *buffer)
2349 {
2350 unsigned int pos = LID_RESUME_S5;
2351
2352 while (pos < LID_RESUME_MAX) {
2353 if (&lid_ctl->attrs[pos].attr == &attr->attr)
2354 return sysfs_emit(buffer, "%d\n",
2355 (lid_ctl->status >> pos) & 0x01);
2356 pos++;
2357 }
2358 return -EINVAL;
2359 }
2360
2361 static int sony_nc_lid_resume_setup(struct platform_device *pd,
2362 unsigned int handle)
2363 {
2364 unsigned int result;
2365 int i;
2366
2367 if (sony_call_snc_handle(handle, 0x0000, &result))
2368 return -EIO;
2369
2370 lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL);
2371 if (!lid_ctl)
2372 return -ENOMEM;
2373
2374 lid_ctl->status = result & 0x7;
2375 lid_ctl->handle = handle;
2376
2377 sysfs_attr_init(&lid_ctl->attrs[0].attr);
2378 lid_ctl->attrs[LID_RESUME_S5].attr.name = "lid_resume_S5";
2379 lid_ctl->attrs[LID_RESUME_S5].attr.mode = S_IRUGO | S_IWUSR;
2380 lid_ctl->attrs[LID_RESUME_S5].show = sony_nc_lid_resume_show;
2381 lid_ctl->attrs[LID_RESUME_S5].store = sony_nc_lid_resume_store;
2382
2383 if (handle == 0x0119) {
2384 sysfs_attr_init(&lid_ctl->attrs[1].attr);
2385 lid_ctl->attrs[LID_RESUME_S4].attr.name = "lid_resume_S4";
2386 lid_ctl->attrs[LID_RESUME_S4].attr.mode = S_IRUGO | S_IWUSR;
2387 lid_ctl->attrs[LID_RESUME_S4].show = sony_nc_lid_resume_show;
2388 lid_ctl->attrs[LID_RESUME_S4].store = sony_nc_lid_resume_store;
2389
2390 sysfs_attr_init(&lid_ctl->attrs[2].attr);
2391 lid_ctl->attrs[LID_RESUME_S3].attr.name = "lid_resume_S3";
2392 lid_ctl->attrs[LID_RESUME_S3].attr.mode = S_IRUGO | S_IWUSR;
2393 lid_ctl->attrs[LID_RESUME_S3].show = sony_nc_lid_resume_show;
2394 lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store;
2395 }
2396 for (i = 0; i < LID_RESUME_MAX &&
2397 lid_ctl->attrs[i].attr.name; i++) {
2398 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]);
2399 if (result)
2400 goto liderror;
2401 }
2402
2403 return 0;
2404
2405 liderror:
2406 for (i--; i >= 0; i--)
2407 device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2408
2409 kfree(lid_ctl);
2410 lid_ctl = NULL;
2411
2412 return result;
2413 }
2414
2415 static void sony_nc_lid_resume_cleanup(struct platform_device *pd)
2416 {
2417 int i;
2418
2419 if (lid_ctl) {
2420 for (i = 0; i < LID_RESUME_MAX; i++) {
2421 if (!lid_ctl->attrs[i].attr.name)
2422 break;
2423
2424 device_remove_file(&pd->dev, &lid_ctl->attrs[i]);
2425 }
2426
2427 kfree(lid_ctl);
2428 lid_ctl = NULL;
2429 }
2430 }
2431
2432
2433 enum gfx_switch {
2434 SPEED,
2435 STAMINA,
2436 AUTO
2437 };
2438 struct snc_gfx_switch_control {
2439 struct device_attribute attr;
2440 unsigned int handle;
2441 };
2442 static struct snc_gfx_switch_control *gfxs_ctl;
2443
2444
2445 static int __sony_nc_gfx_switch_status_get(void)
2446 {
2447 unsigned int result;
2448
2449 if (sony_call_snc_handle(gfxs_ctl->handle,
2450 gfxs_ctl->handle == 0x015B ? 0x0000 : 0x0100,
2451 &result))
2452 return -EIO;
2453
2454 switch (gfxs_ctl->handle) {
2455 case 0x0146:
2456
2457
2458
2459 return result & 0x1 ? SPEED : STAMINA;
2460 case 0x015B:
2461
2462
2463
2464 return result & 0x1 ? STAMINA : SPEED;
2465 case 0x0128:
2466
2467
2468
2469
2470 dprintk("GFX Status: 0x%x\n", result);
2471 return result & 0x80 ? AUTO :
2472 result & 0x02 ? STAMINA : SPEED;
2473 }
2474 return -EINVAL;
2475 }
2476
2477 static ssize_t sony_nc_gfx_switch_status_show(struct device *dev,
2478 struct device_attribute *attr,
2479 char *buffer)
2480 {
2481 int pos = __sony_nc_gfx_switch_status_get();
2482
2483 if (pos < 0)
2484 return pos;
2485
2486 return sysfs_emit(buffer, "%s\n",
2487 pos == SPEED ? "speed" :
2488 pos == STAMINA ? "stamina" :
2489 pos == AUTO ? "auto" : "unknown");
2490 }
2491
2492 static int sony_nc_gfx_switch_setup(struct platform_device *pd,
2493 unsigned int handle)
2494 {
2495 unsigned int result;
2496
2497 gfxs_ctl = kzalloc(sizeof(struct snc_gfx_switch_control), GFP_KERNEL);
2498 if (!gfxs_ctl)
2499 return -ENOMEM;
2500
2501 gfxs_ctl->handle = handle;
2502
2503 sysfs_attr_init(&gfxs_ctl->attr.attr);
2504 gfxs_ctl->attr.attr.name = "gfx_switch_status";
2505 gfxs_ctl->attr.attr.mode = S_IRUGO;
2506 gfxs_ctl->attr.show = sony_nc_gfx_switch_status_show;
2507
2508 result = device_create_file(&pd->dev, &gfxs_ctl->attr);
2509 if (result)
2510 goto gfxerror;
2511
2512 return 0;
2513
2514 gfxerror:
2515 kfree(gfxs_ctl);
2516 gfxs_ctl = NULL;
2517
2518 return result;
2519 }
2520
2521 static void sony_nc_gfx_switch_cleanup(struct platform_device *pd)
2522 {
2523 if (gfxs_ctl) {
2524 device_remove_file(&pd->dev, &gfxs_ctl->attr);
2525
2526 kfree(gfxs_ctl);
2527 gfxs_ctl = NULL;
2528 }
2529 }
2530
2531
2532 static struct device_attribute *hsc_handle;
2533
2534 static ssize_t sony_nc_highspeed_charging_store(struct device *dev,
2535 struct device_attribute *attr,
2536 const char *buffer, size_t count)
2537 {
2538 unsigned int result;
2539 unsigned long value;
2540
2541 if (count > 31)
2542 return -EINVAL;
2543
2544 if (kstrtoul(buffer, 10, &value) || value > 1)
2545 return -EINVAL;
2546
2547 if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result))
2548 return -EIO;
2549
2550 return count;
2551 }
2552
2553 static ssize_t sony_nc_highspeed_charging_show(struct device *dev,
2554 struct device_attribute *attr, char *buffer)
2555 {
2556 unsigned int result;
2557
2558 if (sony_call_snc_handle(0x0131, 0x0100, &result))
2559 return -EIO;
2560
2561 return sysfs_emit(buffer, "%d\n", result & 0x01);
2562 }
2563
2564 static int sony_nc_highspeed_charging_setup(struct platform_device *pd)
2565 {
2566 unsigned int result;
2567
2568 if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) {
2569
2570
2571
2572 pr_info("No High Speed Charging capability found\n");
2573 return 0;
2574 }
2575
2576 hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2577 if (!hsc_handle)
2578 return -ENOMEM;
2579
2580 sysfs_attr_init(&hsc_handle->attr);
2581 hsc_handle->attr.name = "battery_highspeed_charging";
2582 hsc_handle->attr.mode = S_IRUGO | S_IWUSR;
2583 hsc_handle->show = sony_nc_highspeed_charging_show;
2584 hsc_handle->store = sony_nc_highspeed_charging_store;
2585
2586 result = device_create_file(&pd->dev, hsc_handle);
2587 if (result) {
2588 kfree(hsc_handle);
2589 hsc_handle = NULL;
2590 return result;
2591 }
2592
2593 return 0;
2594 }
2595
2596 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd)
2597 {
2598 if (hsc_handle) {
2599 device_remove_file(&pd->dev, hsc_handle);
2600 kfree(hsc_handle);
2601 hsc_handle = NULL;
2602 }
2603 }
2604
2605
2606 static struct device_attribute *lowbatt_handle;
2607
2608 static ssize_t sony_nc_lowbatt_store(struct device *dev,
2609 struct device_attribute *attr,
2610 const char *buffer, size_t count)
2611 {
2612 unsigned int result;
2613 unsigned long value;
2614
2615 if (count > 31)
2616 return -EINVAL;
2617
2618 if (kstrtoul(buffer, 10, &value) || value > 1)
2619 return -EINVAL;
2620
2621 if (sony_call_snc_handle(0x0121, value << 8, &result))
2622 return -EIO;
2623
2624 return count;
2625 }
2626
2627 static ssize_t sony_nc_lowbatt_show(struct device *dev,
2628 struct device_attribute *attr, char *buffer)
2629 {
2630 unsigned int result;
2631
2632 if (sony_call_snc_handle(0x0121, 0x0200, &result))
2633 return -EIO;
2634
2635 return sysfs_emit(buffer, "%d\n", result & 1);
2636 }
2637
2638 static int sony_nc_lowbatt_setup(struct platform_device *pd)
2639 {
2640 unsigned int result;
2641
2642 lowbatt_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2643 if (!lowbatt_handle)
2644 return -ENOMEM;
2645
2646 sysfs_attr_init(&lowbatt_handle->attr);
2647 lowbatt_handle->attr.name = "lowbatt_hibernate";
2648 lowbatt_handle->attr.mode = S_IRUGO | S_IWUSR;
2649 lowbatt_handle->show = sony_nc_lowbatt_show;
2650 lowbatt_handle->store = sony_nc_lowbatt_store;
2651
2652 result = device_create_file(&pd->dev, lowbatt_handle);
2653 if (result) {
2654 kfree(lowbatt_handle);
2655 lowbatt_handle = NULL;
2656 return result;
2657 }
2658
2659 return 0;
2660 }
2661
2662 static void sony_nc_lowbatt_cleanup(struct platform_device *pd)
2663 {
2664 if (lowbatt_handle) {
2665 device_remove_file(&pd->dev, lowbatt_handle);
2666 kfree(lowbatt_handle);
2667 lowbatt_handle = NULL;
2668 }
2669 }
2670
2671
2672 static struct device_attribute *fan_handle, *hsf_handle;
2673
2674 static ssize_t sony_nc_hsfan_store(struct device *dev,
2675 struct device_attribute *attr,
2676 const char *buffer, size_t count)
2677 {
2678 unsigned int result;
2679 unsigned long value;
2680
2681 if (count > 31)
2682 return -EINVAL;
2683
2684 if (kstrtoul(buffer, 10, &value) || value > 1)
2685 return -EINVAL;
2686
2687 if (sony_call_snc_handle(0x0149, value << 0x10 | 0x0200, &result))
2688 return -EIO;
2689
2690 return count;
2691 }
2692
2693 static ssize_t sony_nc_hsfan_show(struct device *dev,
2694 struct device_attribute *attr, char *buffer)
2695 {
2696 unsigned int result;
2697
2698 if (sony_call_snc_handle(0x0149, 0x0100, &result))
2699 return -EIO;
2700
2701 return sysfs_emit(buffer, "%d\n", result & 0x01);
2702 }
2703
2704 static ssize_t sony_nc_fanspeed_show(struct device *dev,
2705 struct device_attribute *attr, char *buffer)
2706 {
2707 unsigned int result;
2708
2709 if (sony_call_snc_handle(0x0149, 0x0300, &result))
2710 return -EIO;
2711
2712 return sysfs_emit(buffer, "%d\n", result & 0xff);
2713 }
2714
2715 static int sony_nc_fanspeed_setup(struct platform_device *pd)
2716 {
2717 unsigned int result;
2718
2719 fan_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2720 if (!fan_handle)
2721 return -ENOMEM;
2722
2723 hsf_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2724 if (!hsf_handle) {
2725 result = -ENOMEM;
2726 goto out_hsf_handle_alloc;
2727 }
2728
2729 sysfs_attr_init(&fan_handle->attr);
2730 fan_handle->attr.name = "fanspeed";
2731 fan_handle->attr.mode = S_IRUGO;
2732 fan_handle->show = sony_nc_fanspeed_show;
2733 fan_handle->store = NULL;
2734
2735 sysfs_attr_init(&hsf_handle->attr);
2736 hsf_handle->attr.name = "fan_forced";
2737 hsf_handle->attr.mode = S_IRUGO | S_IWUSR;
2738 hsf_handle->show = sony_nc_hsfan_show;
2739 hsf_handle->store = sony_nc_hsfan_store;
2740
2741 result = device_create_file(&pd->dev, fan_handle);
2742 if (result)
2743 goto out_fan_handle;
2744
2745 result = device_create_file(&pd->dev, hsf_handle);
2746 if (result)
2747 goto out_hsf_handle;
2748
2749 return 0;
2750
2751 out_hsf_handle:
2752 device_remove_file(&pd->dev, fan_handle);
2753
2754 out_fan_handle:
2755 kfree(hsf_handle);
2756 hsf_handle = NULL;
2757
2758 out_hsf_handle_alloc:
2759 kfree(fan_handle);
2760 fan_handle = NULL;
2761 return result;
2762 }
2763
2764 static void sony_nc_fanspeed_cleanup(struct platform_device *pd)
2765 {
2766 if (fan_handle) {
2767 device_remove_file(&pd->dev, fan_handle);
2768 kfree(fan_handle);
2769 fan_handle = NULL;
2770 }
2771 if (hsf_handle) {
2772 device_remove_file(&pd->dev, hsf_handle);
2773 kfree(hsf_handle);
2774 hsf_handle = NULL;
2775 }
2776 }
2777
2778
2779 static struct device_attribute *uc_handle;
2780
2781 static ssize_t sony_nc_usb_charge_store(struct device *dev,
2782 struct device_attribute *attr,
2783 const char *buffer, size_t count)
2784 {
2785 unsigned int result;
2786 unsigned long value;
2787
2788 if (count > 31)
2789 return -EINVAL;
2790
2791 if (kstrtoul(buffer, 10, &value) || value > 1)
2792 return -EINVAL;
2793
2794 if (sony_call_snc_handle(0x0155, value << 0x10 | 0x0100, &result))
2795 return -EIO;
2796
2797 return count;
2798 }
2799
2800 static ssize_t sony_nc_usb_charge_show(struct device *dev,
2801 struct device_attribute *attr, char *buffer)
2802 {
2803 unsigned int result;
2804
2805 if (sony_call_snc_handle(0x0155, 0x0000, &result))
2806 return -EIO;
2807
2808 return sysfs_emit(buffer, "%d\n", result & 0x01);
2809 }
2810
2811 static int sony_nc_usb_charge_setup(struct platform_device *pd)
2812 {
2813 unsigned int result;
2814
2815 if (sony_call_snc_handle(0x0155, 0x0000, &result) || !(result & 0x01)) {
2816
2817
2818
2819 pr_info("No USB Charge capability found\n");
2820 return 0;
2821 }
2822
2823 uc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2824 if (!uc_handle)
2825 return -ENOMEM;
2826
2827 sysfs_attr_init(&uc_handle->attr);
2828 uc_handle->attr.name = "usb_charge";
2829 uc_handle->attr.mode = S_IRUGO | S_IWUSR;
2830 uc_handle->show = sony_nc_usb_charge_show;
2831 uc_handle->store = sony_nc_usb_charge_store;
2832
2833 result = device_create_file(&pd->dev, uc_handle);
2834 if (result) {
2835 kfree(uc_handle);
2836 uc_handle = NULL;
2837 return result;
2838 }
2839
2840 return 0;
2841 }
2842
2843 static void sony_nc_usb_charge_cleanup(struct platform_device *pd)
2844 {
2845 if (uc_handle) {
2846 device_remove_file(&pd->dev, uc_handle);
2847 kfree(uc_handle);
2848 uc_handle = NULL;
2849 }
2850 }
2851
2852
2853 static struct device_attribute *panel_handle;
2854
2855 static ssize_t sony_nc_panelid_show(struct device *dev,
2856 struct device_attribute *attr, char *buffer)
2857 {
2858 unsigned int result;
2859
2860 if (sony_call_snc_handle(0x011D, 0x0000, &result))
2861 return -EIO;
2862
2863 return sysfs_emit(buffer, "%d\n", result);
2864 }
2865
2866 static int sony_nc_panelid_setup(struct platform_device *pd)
2867 {
2868 unsigned int result;
2869
2870 panel_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2871 if (!panel_handle)
2872 return -ENOMEM;
2873
2874 sysfs_attr_init(&panel_handle->attr);
2875 panel_handle->attr.name = "panel_id";
2876 panel_handle->attr.mode = S_IRUGO;
2877 panel_handle->show = sony_nc_panelid_show;
2878 panel_handle->store = NULL;
2879
2880 result = device_create_file(&pd->dev, panel_handle);
2881 if (result) {
2882 kfree(panel_handle);
2883 panel_handle = NULL;
2884 return result;
2885 }
2886
2887 return 0;
2888 }
2889
2890 static void sony_nc_panelid_cleanup(struct platform_device *pd)
2891 {
2892 if (panel_handle) {
2893 device_remove_file(&pd->dev, panel_handle);
2894 kfree(panel_handle);
2895 panel_handle = NULL;
2896 }
2897 }
2898
2899
2900 static struct device_attribute *sc_handle;
2901
2902 static ssize_t sony_nc_smart_conn_store(struct device *dev,
2903 struct device_attribute *attr,
2904 const char *buffer, size_t count)
2905 {
2906 unsigned int result;
2907 unsigned long value;
2908
2909 if (count > 31)
2910 return -EINVAL;
2911
2912 if (kstrtoul(buffer, 10, &value) || value > 1)
2913 return -EINVAL;
2914
2915 if (sony_call_snc_handle(0x0168, value << 0x10, &result))
2916 return -EIO;
2917
2918 return count;
2919 }
2920
2921 static int sony_nc_smart_conn_setup(struct platform_device *pd)
2922 {
2923 unsigned int result;
2924
2925 sc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2926 if (!sc_handle)
2927 return -ENOMEM;
2928
2929 sysfs_attr_init(&sc_handle->attr);
2930 sc_handle->attr.name = "smart_connect";
2931 sc_handle->attr.mode = S_IWUSR;
2932 sc_handle->show = NULL;
2933 sc_handle->store = sony_nc_smart_conn_store;
2934
2935 result = device_create_file(&pd->dev, sc_handle);
2936 if (result) {
2937 kfree(sc_handle);
2938 sc_handle = NULL;
2939 return result;
2940 }
2941
2942 return 0;
2943 }
2944
2945 static void sony_nc_smart_conn_cleanup(struct platform_device *pd)
2946 {
2947 if (sc_handle) {
2948 device_remove_file(&pd->dev, sc_handle);
2949 kfree(sc_handle);
2950 sc_handle = NULL;
2951 }
2952 }
2953
2954
2955 struct touchpad_control {
2956 struct device_attribute attr;
2957 int handle;
2958 };
2959 static struct touchpad_control *tp_ctl;
2960
2961 static ssize_t sony_nc_touchpad_store(struct device *dev,
2962 struct device_attribute *attr, const char *buffer, size_t count)
2963 {
2964 unsigned int result;
2965 unsigned long value;
2966
2967 if (count > 31)
2968 return -EINVAL;
2969
2970 if (kstrtoul(buffer, 10, &value) || value > 1)
2971 return -EINVAL;
2972
2973
2974
2975
2976 if (sony_call_snc_handle(tp_ctl->handle,
2977 (!value << 0x10) | 0x100, &result))
2978 return -EIO;
2979
2980 return count;
2981 }
2982
2983 static ssize_t sony_nc_touchpad_show(struct device *dev,
2984 struct device_attribute *attr, char *buffer)
2985 {
2986 unsigned int result;
2987
2988 if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result))
2989 return -EINVAL;
2990
2991 return sysfs_emit(buffer, "%d\n", !(result & 0x01));
2992 }
2993
2994 static int sony_nc_touchpad_setup(struct platform_device *pd,
2995 unsigned int handle)
2996 {
2997 int ret = 0;
2998
2999 tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL);
3000 if (!tp_ctl)
3001 return -ENOMEM;
3002
3003 tp_ctl->handle = handle;
3004
3005 sysfs_attr_init(&tp_ctl->attr.attr);
3006 tp_ctl->attr.attr.name = "touchpad";
3007 tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR;
3008 tp_ctl->attr.show = sony_nc_touchpad_show;
3009 tp_ctl->attr.store = sony_nc_touchpad_store;
3010
3011 ret = device_create_file(&pd->dev, &tp_ctl->attr);
3012 if (ret) {
3013 kfree(tp_ctl);
3014 tp_ctl = NULL;
3015 }
3016
3017 return ret;
3018 }
3019
3020 static void sony_nc_touchpad_cleanup(struct platform_device *pd)
3021 {
3022 if (tp_ctl) {
3023 device_remove_file(&pd->dev, &tp_ctl->attr);
3024 kfree(tp_ctl);
3025 tp_ctl = NULL;
3026 }
3027 }
3028
3029 static void sony_nc_backlight_ng_read_limits(int handle,
3030 struct sony_backlight_props *props)
3031 {
3032 u64 offset;
3033 int i;
3034 int lvl_table_len = 0;
3035 u8 min = 0xff, max = 0x00;
3036 unsigned char buffer[32] = { 0 };
3037
3038 props->handle = handle;
3039 props->offset = 0;
3040 props->maxlvl = 0xff;
3041
3042 offset = sony_find_snc_handle(handle);
3043
3044
3045
3046
3047 i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer,
3048 32);
3049 if (i < 0)
3050 return;
3051
3052 switch (handle) {
3053 case 0x012f:
3054 case 0x0137:
3055 lvl_table_len = 9;
3056 break;
3057 case 0x143:
3058 case 0x14b:
3059 case 0x14c:
3060 lvl_table_len = 16;
3061 break;
3062 }
3063
3064
3065
3066
3067
3068 for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
3069
3070 dprintk("Brightness level: %d\n", buffer[i]);
3071
3072 if (!buffer[i])
3073 break;
3074
3075 if (buffer[i] > max)
3076 max = buffer[i];
3077 if (buffer[i] < min)
3078 min = buffer[i];
3079 }
3080 props->offset = min;
3081 props->maxlvl = max;
3082 dprintk("Brightness levels: min=%d max=%d\n", props->offset,
3083 props->maxlvl);
3084 }
3085
3086 static void sony_nc_backlight_setup(void)
3087 {
3088 int max_brightness = 0;
3089 const struct backlight_ops *ops = NULL;
3090 struct backlight_properties props;
3091
3092 if (sony_find_snc_handle(0x12f) >= 0) {
3093 ops = &sony_backlight_ng_ops;
3094 sony_bl_props.cmd_base = 0x0100;
3095 sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
3096 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
3097
3098 } else if (sony_find_snc_handle(0x137) >= 0) {
3099 ops = &sony_backlight_ng_ops;
3100 sony_bl_props.cmd_base = 0x0100;
3101 sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
3102 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
3103
3104 } else if (sony_find_snc_handle(0x143) >= 0) {
3105 ops = &sony_backlight_ng_ops;
3106 sony_bl_props.cmd_base = 0x3000;
3107 sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
3108 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
3109
3110 } else if (sony_find_snc_handle(0x14b) >= 0) {
3111 ops = &sony_backlight_ng_ops;
3112 sony_bl_props.cmd_base = 0x3000;
3113 sony_nc_backlight_ng_read_limits(0x14b, &sony_bl_props);
3114 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
3115
3116 } else if (sony_find_snc_handle(0x14c) >= 0) {
3117 ops = &sony_backlight_ng_ops;
3118 sony_bl_props.cmd_base = 0x3000;
3119 sony_nc_backlight_ng_read_limits(0x14c, &sony_bl_props);
3120 max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
3121
3122 } else if (acpi_has_method(sony_nc_acpi_handle, "GBRT")) {
3123 ops = &sony_backlight_ops;
3124 max_brightness = SONY_MAX_BRIGHTNESS - 1;
3125
3126 } else
3127 return;
3128
3129 memset(&props, 0, sizeof(struct backlight_properties));
3130 props.type = BACKLIGHT_PLATFORM;
3131 props.max_brightness = max_brightness;
3132 sony_bl_props.dev = backlight_device_register("sony", NULL,
3133 &sony_bl_props,
3134 ops, &props);
3135
3136 if (IS_ERR(sony_bl_props.dev)) {
3137 pr_warn("unable to register backlight device\n");
3138 sony_bl_props.dev = NULL;
3139 } else
3140 sony_bl_props.dev->props.brightness =
3141 ops->get_brightness(sony_bl_props.dev);
3142 }
3143
3144 static void sony_nc_backlight_cleanup(void)
3145 {
3146 backlight_device_unregister(sony_bl_props.dev);
3147 }
3148
3149 static int sony_nc_add(struct acpi_device *device)
3150 {
3151 acpi_status status;
3152 int result = 0;
3153 struct sony_nc_value *item;
3154
3155 sony_nc_acpi_device = device;
3156 strcpy(acpi_device_class(device), "sony/hotkey");
3157
3158 sony_nc_acpi_handle = device->handle;
3159
3160
3161 result = acpi_bus_get_status(device);
3162
3163 if (!result && !device->status.present) {
3164 dprintk("Device not present\n");
3165 result = -ENODEV;
3166 goto outwalk;
3167 }
3168
3169 result = sony_pf_add();
3170 if (result)
3171 goto outpresent;
3172
3173 if (debug) {
3174 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
3175 sony_nc_acpi_handle, 1, sony_walk_callback,
3176 NULL, NULL, NULL);
3177 if (ACPI_FAILURE(status)) {
3178 pr_warn("unable to walk acpi resources\n");
3179 result = -ENODEV;
3180 goto outpresent;
3181 }
3182 }
3183
3184 result = sony_laptop_setup_input(device);
3185 if (result) {
3186 pr_err("Unable to create input devices\n");
3187 goto outplatform;
3188 }
3189
3190 if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
3191 int arg = 1;
3192 if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
3193 dprintk("ECON Method failed\n");
3194 }
3195
3196 if (acpi_has_method(sony_nc_acpi_handle, "SN00")) {
3197 dprintk("Doing SNC setup\n");
3198
3199 result = sony_nc_handles_setup(sony_pf_device);
3200 if (!result)
3201 sony_nc_function_setup(device, sony_pf_device);
3202 }
3203
3204 if (acpi_video_get_backlight_type() == acpi_backlight_vendor)
3205 sony_nc_backlight_setup();
3206
3207
3208 for (item = sony_nc_values; item->name; ++item) {
3209
3210 if (!debug && item->debug)
3211 continue;
3212
3213
3214 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
3215 if (acpi_has_method(sony_nc_acpi_handle,
3216 *item->acpiget)) {
3217 dprintk("Found %s getter: %s\n",
3218 item->name, *item->acpiget);
3219 item->devattr.attr.mode |= S_IRUGO;
3220 break;
3221 }
3222 }
3223
3224
3225 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
3226 if (acpi_has_method(sony_nc_acpi_handle,
3227 *item->acpiset)) {
3228 dprintk("Found %s setter: %s\n",
3229 item->name, *item->acpiset);
3230 item->devattr.attr.mode |= S_IWUSR;
3231 break;
3232 }
3233 }
3234
3235 if (item->devattr.attr.mode != 0) {
3236 result =
3237 device_create_file(&sony_pf_device->dev,
3238 &item->devattr);
3239 if (result)
3240 goto out_sysfs;
3241 }
3242 }
3243
3244 pr_info("SNC setup done.\n");
3245 return 0;
3246
3247 out_sysfs:
3248 for (item = sony_nc_values; item->name; ++item) {
3249 device_remove_file(&sony_pf_device->dev, &item->devattr);
3250 }
3251 sony_nc_backlight_cleanup();
3252 sony_nc_function_cleanup(sony_pf_device);
3253 sony_nc_handles_cleanup(sony_pf_device);
3254
3255 outplatform:
3256 sony_laptop_remove_input();
3257
3258 outpresent:
3259 sony_pf_remove();
3260
3261 outwalk:
3262 sony_nc_rfkill_cleanup();
3263 return result;
3264 }
3265
3266 static int sony_nc_remove(struct acpi_device *device)
3267 {
3268 struct sony_nc_value *item;
3269
3270 sony_nc_backlight_cleanup();
3271
3272 sony_nc_acpi_device = NULL;
3273
3274 for (item = sony_nc_values; item->name; ++item) {
3275 device_remove_file(&sony_pf_device->dev, &item->devattr);
3276 }
3277
3278 sony_nc_function_cleanup(sony_pf_device);
3279 sony_nc_handles_cleanup(sony_pf_device);
3280 sony_pf_remove();
3281 sony_laptop_remove_input();
3282 dprintk(SONY_NC_DRIVER_NAME " removed.\n");
3283
3284 return 0;
3285 }
3286
3287 static const struct acpi_device_id sony_device_ids[] = {
3288 {SONY_NC_HID, 0},
3289 {SONY_PIC_HID, 0},
3290 {"", 0},
3291 };
3292 MODULE_DEVICE_TABLE(acpi, sony_device_ids);
3293
3294 static const struct acpi_device_id sony_nc_device_ids[] = {
3295 {SONY_NC_HID, 0},
3296 {"", 0},
3297 };
3298
3299 static struct acpi_driver sony_nc_driver = {
3300 .name = SONY_NC_DRIVER_NAME,
3301 .class = SONY_NC_CLASS,
3302 .ids = sony_nc_device_ids,
3303 .owner = THIS_MODULE,
3304 .ops = {
3305 .add = sony_nc_add,
3306 .remove = sony_nc_remove,
3307 .notify = sony_nc_notify,
3308 },
3309 .drv.pm = &sony_nc_pm,
3310 };
3311
3312
3313
3314 #define SONYPI_DEVICE_TYPE1 0x00000001
3315 #define SONYPI_DEVICE_TYPE2 0x00000002
3316 #define SONYPI_DEVICE_TYPE3 0x00000004
3317
3318 #define SONYPI_TYPE1_OFFSET 0x04
3319 #define SONYPI_TYPE2_OFFSET 0x12
3320 #define SONYPI_TYPE3_OFFSET 0x12
3321
3322 struct sony_pic_ioport {
3323 struct acpi_resource_io io1;
3324 struct acpi_resource_io io2;
3325 struct list_head list;
3326 };
3327
3328 struct sony_pic_irq {
3329 struct acpi_resource_irq irq;
3330 struct list_head list;
3331 };
3332
3333 struct sonypi_eventtypes {
3334 u8 data;
3335 unsigned long mask;
3336 struct sonypi_event *events;
3337 };
3338
3339 struct sony_pic_dev {
3340 struct acpi_device *acpi_dev;
3341 struct sony_pic_irq *cur_irq;
3342 struct sony_pic_ioport *cur_ioport;
3343 struct list_head interrupts;
3344 struct list_head ioports;
3345 struct mutex lock;
3346 struct sonypi_eventtypes *event_types;
3347 int (*handle_irq)(const u8, const u8);
3348 int model;
3349 u16 evport_offset;
3350 u8 camera_power;
3351 u8 bluetooth_power;
3352 u8 wwan_power;
3353 };
3354
3355 static struct sony_pic_dev spic_dev = {
3356 .interrupts = LIST_HEAD_INIT(spic_dev.interrupts),
3357 .ioports = LIST_HEAD_INIT(spic_dev.ioports),
3358 };
3359
3360 static int spic_drv_registered;
3361
3362
3363 #define SONYPI_JOGGER_MASK 0x00000001
3364 #define SONYPI_CAPTURE_MASK 0x00000002
3365 #define SONYPI_FNKEY_MASK 0x00000004
3366 #define SONYPI_BLUETOOTH_MASK 0x00000008
3367 #define SONYPI_PKEY_MASK 0x00000010
3368 #define SONYPI_BACK_MASK 0x00000020
3369 #define SONYPI_HELP_MASK 0x00000040
3370 #define SONYPI_LID_MASK 0x00000080
3371 #define SONYPI_ZOOM_MASK 0x00000100
3372 #define SONYPI_THUMBPHRASE_MASK 0x00000200
3373 #define SONYPI_MEYE_MASK 0x00000400
3374 #define SONYPI_MEMORYSTICK_MASK 0x00000800
3375 #define SONYPI_BATTERY_MASK 0x00001000
3376 #define SONYPI_WIRELESS_MASK 0x00002000
3377
3378 struct sonypi_event {
3379 u8 data;
3380 u8 event;
3381 };
3382
3383
3384 static struct sonypi_event sonypi_releaseev[] = {
3385 { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
3386 { 0, 0 }
3387 };
3388
3389
3390 static struct sonypi_event sonypi_joggerev[] = {
3391 { 0x1f, SONYPI_EVENT_JOGDIAL_UP },
3392 { 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
3393 { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
3394 { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
3395 { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
3396 { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
3397 { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
3398 { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
3399 { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
3400 { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
3401 { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
3402 { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
3403 { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
3404 { 0, 0 }
3405 };
3406
3407
3408 static struct sonypi_event sonypi_captureev[] = {
3409 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
3410 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
3411 { 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
3412 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
3413 { 0, 0 }
3414 };
3415
3416
3417 static struct sonypi_event sonypi_fnkeyev[] = {
3418 { 0x10, SONYPI_EVENT_FNKEY_ESC },
3419 { 0x11, SONYPI_EVENT_FNKEY_F1 },
3420 { 0x12, SONYPI_EVENT_FNKEY_F2 },
3421 { 0x13, SONYPI_EVENT_FNKEY_F3 },
3422 { 0x14, SONYPI_EVENT_FNKEY_F4 },
3423 { 0x15, SONYPI_EVENT_FNKEY_F5 },
3424 { 0x16, SONYPI_EVENT_FNKEY_F6 },
3425 { 0x17, SONYPI_EVENT_FNKEY_F7 },
3426 { 0x18, SONYPI_EVENT_FNKEY_F8 },
3427 { 0x19, SONYPI_EVENT_FNKEY_F9 },
3428 { 0x1a, SONYPI_EVENT_FNKEY_F10 },
3429 { 0x1b, SONYPI_EVENT_FNKEY_F11 },
3430 { 0x1c, SONYPI_EVENT_FNKEY_F12 },
3431 { 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
3432 { 0x21, SONYPI_EVENT_FNKEY_1 },
3433 { 0x22, SONYPI_EVENT_FNKEY_2 },
3434 { 0x31, SONYPI_EVENT_FNKEY_D },
3435 { 0x32, SONYPI_EVENT_FNKEY_E },
3436 { 0x33, SONYPI_EVENT_FNKEY_F },
3437 { 0x34, SONYPI_EVENT_FNKEY_S },
3438 { 0x35, SONYPI_EVENT_FNKEY_B },
3439 { 0x36, SONYPI_EVENT_FNKEY_ONLY },
3440 { 0, 0 }
3441 };
3442
3443
3444 static struct sonypi_event sonypi_pkeyev[] = {
3445 { 0x01, SONYPI_EVENT_PKEY_P1 },
3446 { 0x02, SONYPI_EVENT_PKEY_P2 },
3447 { 0x04, SONYPI_EVENT_PKEY_P3 },
3448 { 0x20, SONYPI_EVENT_PKEY_P1 },
3449 { 0, 0 }
3450 };
3451
3452
3453 static struct sonypi_event sonypi_blueev[] = {
3454 { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
3455 { 0x59, SONYPI_EVENT_BLUETOOTH_ON },
3456 { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
3457 { 0, 0 }
3458 };
3459
3460
3461 static struct sonypi_event sonypi_wlessev[] = {
3462 { 0x59, SONYPI_EVENT_IGNORE },
3463 { 0x5a, SONYPI_EVENT_IGNORE },
3464 { 0, 0 }
3465 };
3466
3467
3468 static struct sonypi_event sonypi_backev[] = {
3469 { 0x20, SONYPI_EVENT_BACK_PRESSED },
3470 { 0, 0 }
3471 };
3472
3473
3474 static struct sonypi_event sonypi_helpev[] = {
3475 { 0x3b, SONYPI_EVENT_HELP_PRESSED },
3476 { 0, 0 }
3477 };
3478
3479
3480
3481 static struct sonypi_event sonypi_lidev[] = {
3482 { 0x51, SONYPI_EVENT_LID_CLOSED },
3483 { 0x50, SONYPI_EVENT_LID_OPENED },
3484 { 0, 0 }
3485 };
3486
3487
3488 static struct sonypi_event sonypi_zoomev[] = {
3489 { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
3490 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
3491 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
3492 { 0x04, SONYPI_EVENT_ZOOM_PRESSED },
3493 { 0, 0 }
3494 };
3495
3496
3497 static struct sonypi_event sonypi_thumbphraseev[] = {
3498 { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
3499 { 0, 0 }
3500 };
3501
3502
3503 static struct sonypi_event sonypi_meyeev[] = {
3504 { 0x00, SONYPI_EVENT_MEYE_FACE },
3505 { 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
3506 { 0, 0 }
3507 };
3508
3509
3510 static struct sonypi_event sonypi_memorystickev[] = {
3511 { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
3512 { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
3513 { 0, 0 }
3514 };
3515
3516
3517 static struct sonypi_event sonypi_batteryev[] = {
3518 { 0x20, SONYPI_EVENT_BATTERY_INSERT },
3519 { 0x30, SONYPI_EVENT_BATTERY_REMOVE },
3520 { 0, 0 }
3521 };
3522
3523
3524 static struct sonypi_event sonypi_volumeev[] = {
3525 { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
3526 { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
3527 { 0, 0 }
3528 };
3529
3530
3531 static struct sonypi_event sonypi_brightnessev[] = {
3532 { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
3533 { 0, 0 }
3534 };
3535
3536 static struct sonypi_eventtypes type1_events[] = {
3537 { 0, 0xffffffff, sonypi_releaseev },
3538 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
3539 { 0x30, SONYPI_LID_MASK, sonypi_lidev },
3540 { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
3541 { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
3542 { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3543 { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3544 { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
3545 { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3546 { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
3547 { 0 },
3548 };
3549 static struct sonypi_eventtypes type2_events[] = {
3550 { 0, 0xffffffff, sonypi_releaseev },
3551 { 0x38, SONYPI_LID_MASK, sonypi_lidev },
3552 { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
3553 { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
3554 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3555 { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
3556 { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
3557 { 0x11, SONYPI_BACK_MASK, sonypi_backev },
3558 { 0x21, SONYPI_HELP_MASK, sonypi_helpev },
3559 { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
3560 { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
3561 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3562 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3563 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3564 { 0 },
3565 };
3566 static struct sonypi_eventtypes type3_events[] = {
3567 { 0, 0xffffffff, sonypi_releaseev },
3568 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
3569 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
3570 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
3571 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
3572 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
3573 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
3574 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
3575 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
3576 { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
3577 { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
3578 { 0 },
3579 };
3580
3581
3582 #define ITERATIONS_LONG 10000
3583 #define ITERATIONS_SHORT 10
3584 #define wait_on_command(command, iterations) { \
3585 unsigned int n = iterations; \
3586 while (--n && (command)) \
3587 udelay(1); \
3588 if (!n) \
3589 dprintk("command failed at %s : %s (line %d)\n", \
3590 __FILE__, __func__, __LINE__); \
3591 }
3592
3593 static u8 sony_pic_call1(u8 dev)
3594 {
3595 u8 v1, v2;
3596
3597 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3598 ITERATIONS_LONG);
3599 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3600 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
3601 v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
3602 dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
3603 return v2;
3604 }
3605
3606 static u8 sony_pic_call2(u8 dev, u8 fn)
3607 {
3608 u8 v1;
3609
3610 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3611 ITERATIONS_LONG);
3612 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3613 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
3614 ITERATIONS_LONG);
3615 outb(fn, spic_dev.cur_ioport->io1.minimum);
3616 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3617 dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
3618 return v1;
3619 }
3620
3621 static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
3622 {
3623 u8 v1;
3624
3625 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3626 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
3627 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3628 outb(fn, spic_dev.cur_ioport->io1.minimum);
3629 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
3630 outb(v, spic_dev.cur_ioport->io1.minimum);
3631 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
3632 dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
3633 dev, fn, v, v1);
3634 return v1;
3635 }
3636
3637
3638
3639
3640 static int type3_handle_irq(const u8 data_mask, const u8 ev)
3641 {
3642
3643
3644
3645
3646
3647
3648
3649 if (data_mask == 0x31) {
3650 if (ev == 0x5c || ev == 0x5f)
3651 sony_pic_call1(0xA0);
3652 else if (ev == 0x61)
3653 sony_pic_call1(0xB3);
3654 return 0;
3655 }
3656 return 1;
3657 }
3658
3659 static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
3660 {
3661 struct pci_dev *pcidev;
3662
3663 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3664 PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
3665 if (pcidev) {
3666 dev->model = SONYPI_DEVICE_TYPE1;
3667 dev->evport_offset = SONYPI_TYPE1_OFFSET;
3668 dev->event_types = type1_events;
3669 goto out;
3670 }
3671
3672 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3673 PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
3674 if (pcidev) {
3675 dev->model = SONYPI_DEVICE_TYPE2;
3676 dev->evport_offset = SONYPI_TYPE2_OFFSET;
3677 dev->event_types = type2_events;
3678 goto out;
3679 }
3680
3681 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3682 PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
3683 if (pcidev) {
3684 dev->model = SONYPI_DEVICE_TYPE3;
3685 dev->handle_irq = type3_handle_irq;
3686 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3687 dev->event_types = type3_events;
3688 goto out;
3689 }
3690
3691 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3692 PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
3693 if (pcidev) {
3694 dev->model = SONYPI_DEVICE_TYPE3;
3695 dev->handle_irq = type3_handle_irq;
3696 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3697 dev->event_types = type3_events;
3698 goto out;
3699 }
3700
3701 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
3702 PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
3703 if (pcidev) {
3704 dev->model = SONYPI_DEVICE_TYPE3;
3705 dev->handle_irq = type3_handle_irq;
3706 dev->evport_offset = SONYPI_TYPE3_OFFSET;
3707 dev->event_types = type3_events;
3708 goto out;
3709 }
3710
3711
3712 dev->model = SONYPI_DEVICE_TYPE2;
3713 dev->evport_offset = SONYPI_TYPE2_OFFSET;
3714 dev->event_types = type2_events;
3715
3716 out:
3717 pci_dev_put(pcidev);
3718
3719 pr_info("detected Type%d model\n",
3720 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
3721 dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
3722 }
3723
3724
3725 #define SONYPI_CAMERA_PICTURE 5
3726 #define SONYPI_CAMERA_CONTROL 0x10
3727
3728 #define SONYPI_CAMERA_BRIGHTNESS 0
3729 #define SONYPI_CAMERA_CONTRAST 1
3730 #define SONYPI_CAMERA_HUE 2
3731 #define SONYPI_CAMERA_COLOR 3
3732 #define SONYPI_CAMERA_SHARPNESS 4
3733
3734 #define SONYPI_CAMERA_EXPOSURE_MASK 0xC
3735 #define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
3736 #define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30
3737 #define SONYPI_CAMERA_MUTE_MASK 0x40
3738
3739
3740 #define SONYPI_CAMERA_AGC 6
3741 #define SONYPI_CAMERA_AGC_MASK 0x30
3742 #define SONYPI_CAMERA_SHUTTER_MASK 0x7
3743
3744 #define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
3745 #define SONYPI_CAMERA_CONTROL 0x10
3746
3747 #define SONYPI_CAMERA_STATUS 7
3748 #define SONYPI_CAMERA_STATUS_READY 0x2
3749 #define SONYPI_CAMERA_STATUS_POSITION 0x4
3750
3751 #define SONYPI_DIRECTION_BACKWARDS 0x4
3752
3753 #define SONYPI_CAMERA_REVISION 8
3754 #define SONYPI_CAMERA_ROMVERSION 9
3755
3756 static int __sony_pic_camera_ready(void)
3757 {
3758 u8 v;
3759
3760 v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
3761 return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
3762 }
3763
3764 static int __sony_pic_camera_off(void)
3765 {
3766 if (!camera) {
3767 pr_warn("camera control not enabled\n");
3768 return -ENODEV;
3769 }
3770
3771 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
3772 SONYPI_CAMERA_MUTE_MASK),
3773 ITERATIONS_SHORT);
3774
3775 if (spic_dev.camera_power) {
3776 sony_pic_call2(0x91, 0);
3777 spic_dev.camera_power = 0;
3778 }
3779 return 0;
3780 }
3781
3782 static int __sony_pic_camera_on(void)
3783 {
3784 int i, j, x;
3785
3786 if (!camera) {
3787 pr_warn("camera control not enabled\n");
3788 return -ENODEV;
3789 }
3790
3791 if (spic_dev.camera_power)
3792 return 0;
3793
3794 for (j = 5; j > 0; j--) {
3795
3796 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
3797 msleep(10);
3798 sony_pic_call1(0x93);
3799
3800 for (i = 400; i > 0; i--) {
3801 if (__sony_pic_camera_ready())
3802 break;
3803 msleep(10);
3804 }
3805 if (i)
3806 break;
3807 }
3808
3809 if (j == 0) {
3810 pr_warn("failed to power on camera\n");
3811 return -ENODEV;
3812 }
3813
3814 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
3815 0x5a),
3816 ITERATIONS_SHORT);
3817
3818 spic_dev.camera_power = 1;
3819 return 0;
3820 }
3821
3822
3823 int sony_pic_camera_command(int command, u8 value)
3824 {
3825 if (!camera)
3826 return -EIO;
3827
3828 mutex_lock(&spic_dev.lock);
3829
3830 switch (command) {
3831 case SONY_PIC_COMMAND_SETCAMERA:
3832 if (value)
3833 __sony_pic_camera_on();
3834 else
3835 __sony_pic_camera_off();
3836 break;
3837 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
3838 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
3839 ITERATIONS_SHORT);
3840 break;
3841 case SONY_PIC_COMMAND_SETCAMERACONTRAST:
3842 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
3843 ITERATIONS_SHORT);
3844 break;
3845 case SONY_PIC_COMMAND_SETCAMERAHUE:
3846 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
3847 ITERATIONS_SHORT);
3848 break;
3849 case SONY_PIC_COMMAND_SETCAMERACOLOR:
3850 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
3851 ITERATIONS_SHORT);
3852 break;
3853 case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
3854 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
3855 ITERATIONS_SHORT);
3856 break;
3857 case SONY_PIC_COMMAND_SETCAMERAPICTURE:
3858 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
3859 ITERATIONS_SHORT);
3860 break;
3861 case SONY_PIC_COMMAND_SETCAMERAAGC:
3862 wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
3863 ITERATIONS_SHORT);
3864 break;
3865 default:
3866 pr_err("sony_pic_camera_command invalid: %d\n", command);
3867 break;
3868 }
3869 mutex_unlock(&spic_dev.lock);
3870 return 0;
3871 }
3872 EXPORT_SYMBOL(sony_pic_camera_command);
3873
3874
3875 static void __sony_pic_set_wwanpower(u8 state)
3876 {
3877 state = !!state;
3878 if (spic_dev.wwan_power == state)
3879 return;
3880 sony_pic_call2(0xB0, state);
3881 sony_pic_call1(0x82);
3882 spic_dev.wwan_power = state;
3883 }
3884
3885 static ssize_t sony_pic_wwanpower_store(struct device *dev,
3886 struct device_attribute *attr,
3887 const char *buffer, size_t count)
3888 {
3889 unsigned long value;
3890 if (count > 31)
3891 return -EINVAL;
3892
3893 if (kstrtoul(buffer, 10, &value))
3894 return -EINVAL;
3895
3896 mutex_lock(&spic_dev.lock);
3897 __sony_pic_set_wwanpower(value);
3898 mutex_unlock(&spic_dev.lock);
3899
3900 return count;
3901 }
3902
3903 static ssize_t sony_pic_wwanpower_show(struct device *dev,
3904 struct device_attribute *attr, char *buffer)
3905 {
3906 ssize_t count;
3907 mutex_lock(&spic_dev.lock);
3908 count = sysfs_emit(buffer, "%d\n", spic_dev.wwan_power);
3909 mutex_unlock(&spic_dev.lock);
3910 return count;
3911 }
3912
3913
3914 static void __sony_pic_set_bluetoothpower(u8 state)
3915 {
3916 state = !!state;
3917 if (spic_dev.bluetooth_power == state)
3918 return;
3919 sony_pic_call2(0x96, state);
3920 sony_pic_call1(0x82);
3921 spic_dev.bluetooth_power = state;
3922 }
3923
3924 static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
3925 struct device_attribute *attr,
3926 const char *buffer, size_t count)
3927 {
3928 unsigned long value;
3929 if (count > 31)
3930 return -EINVAL;
3931
3932 if (kstrtoul(buffer, 10, &value))
3933 return -EINVAL;
3934
3935 mutex_lock(&spic_dev.lock);
3936 __sony_pic_set_bluetoothpower(value);
3937 mutex_unlock(&spic_dev.lock);
3938
3939 return count;
3940 }
3941
3942 static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
3943 struct device_attribute *attr, char *buffer)
3944 {
3945 ssize_t count = 0;
3946 mutex_lock(&spic_dev.lock);
3947 count = sysfs_emit(buffer, "%d\n", spic_dev.bluetooth_power);
3948 mutex_unlock(&spic_dev.lock);
3949 return count;
3950 }
3951
3952
3953
3954 #define SONY_PIC_FAN0_STATUS 0x93
3955 static int sony_pic_set_fanspeed(unsigned long value)
3956 {
3957 return ec_write(SONY_PIC_FAN0_STATUS, value);
3958 }
3959
3960 static int sony_pic_get_fanspeed(u8 *value)
3961 {
3962 return ec_read(SONY_PIC_FAN0_STATUS, value);
3963 }
3964
3965 static ssize_t sony_pic_fanspeed_store(struct device *dev,
3966 struct device_attribute *attr,
3967 const char *buffer, size_t count)
3968 {
3969 unsigned long value;
3970 if (count > 31)
3971 return -EINVAL;
3972
3973 if (kstrtoul(buffer, 10, &value))
3974 return -EINVAL;
3975
3976 if (sony_pic_set_fanspeed(value))
3977 return -EIO;
3978
3979 return count;
3980 }
3981
3982 static ssize_t sony_pic_fanspeed_show(struct device *dev,
3983 struct device_attribute *attr, char *buffer)
3984 {
3985 u8 value = 0;
3986 if (sony_pic_get_fanspeed(&value))
3987 return -EIO;
3988
3989 return sysfs_emit(buffer, "%d\n", value);
3990 }
3991
3992 #define SPIC_ATTR(_name, _mode) \
3993 struct device_attribute spic_attr_##_name = __ATTR(_name, \
3994 _mode, sony_pic_## _name ##_show, \
3995 sony_pic_## _name ##_store)
3996
3997 static SPIC_ATTR(bluetoothpower, 0644);
3998 static SPIC_ATTR(wwanpower, 0644);
3999 static SPIC_ATTR(fanspeed, 0644);
4000
4001 static struct attribute *spic_attributes[] = {
4002 &spic_attr_bluetoothpower.attr,
4003 &spic_attr_wwanpower.attr,
4004 &spic_attr_fanspeed.attr,
4005 NULL
4006 };
4007
4008 static const struct attribute_group spic_attribute_group = {
4009 .attrs = spic_attributes
4010 };
4011
4012
4013 #ifdef CONFIG_SONYPI_COMPAT
4014
4015
4016 #define SONYPI_BAT_FLAGS 0x81
4017 #define SONYPI_LCD_LIGHT 0x96
4018 #define SONYPI_BAT1_PCTRM 0xa0
4019 #define SONYPI_BAT1_LEFT 0xa2
4020 #define SONYPI_BAT1_MAXRT 0xa4
4021 #define SONYPI_BAT2_PCTRM 0xa8
4022 #define SONYPI_BAT2_LEFT 0xaa
4023 #define SONYPI_BAT2_MAXRT 0xac
4024 #define SONYPI_BAT1_MAXTK 0xb0
4025 #define SONYPI_BAT1_FULL 0xb2
4026 #define SONYPI_BAT2_MAXTK 0xb8
4027 #define SONYPI_BAT2_FULL 0xba
4028 #define SONYPI_TEMP_STATUS 0xC1
4029
4030 struct sonypi_compat_s {
4031 struct fasync_struct *fifo_async;
4032 struct kfifo fifo;
4033 spinlock_t fifo_lock;
4034 wait_queue_head_t fifo_proc_list;
4035 atomic_t open_count;
4036 };
4037 static struct sonypi_compat_s sonypi_compat = {
4038 .open_count = ATOMIC_INIT(0),
4039 };
4040
4041 static int sonypi_misc_fasync(int fd, struct file *filp, int on)
4042 {
4043 return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
4044 }
4045
4046 static int sonypi_misc_release(struct inode *inode, struct file *file)
4047 {
4048 atomic_dec(&sonypi_compat.open_count);
4049 return 0;
4050 }
4051
4052 static int sonypi_misc_open(struct inode *inode, struct file *file)
4053 {
4054
4055 unsigned long flags;
4056
4057 spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
4058
4059 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
4060 kfifo_reset(&sonypi_compat.fifo);
4061
4062 spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
4063
4064 return 0;
4065 }
4066
4067 static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
4068 size_t count, loff_t *pos)
4069 {
4070 ssize_t ret;
4071 unsigned char c;
4072
4073 if ((kfifo_len(&sonypi_compat.fifo) == 0) &&
4074 (file->f_flags & O_NONBLOCK))
4075 return -EAGAIN;
4076
4077 ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
4078 kfifo_len(&sonypi_compat.fifo) != 0);
4079 if (ret)
4080 return ret;
4081
4082 while (ret < count &&
4083 (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
4084 &sonypi_compat.fifo_lock) == sizeof(c))) {
4085 if (put_user(c, buf++))
4086 return -EFAULT;
4087 ret++;
4088 }
4089
4090 if (ret > 0) {
4091 struct inode *inode = file_inode(file);
4092 inode->i_atime = current_time(inode);
4093 }
4094
4095 return ret;
4096 }
4097
4098 static __poll_t sonypi_misc_poll(struct file *file, poll_table *wait)
4099 {
4100 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
4101 if (kfifo_len(&sonypi_compat.fifo))
4102 return EPOLLIN | EPOLLRDNORM;
4103 return 0;
4104 }
4105
4106 static int ec_read16(u8 addr, u16 *value)
4107 {
4108 u8 val_lb, val_hb;
4109 if (ec_read(addr, &val_lb))
4110 return -1;
4111 if (ec_read(addr + 1, &val_hb))
4112 return -1;
4113 *value = val_lb | (val_hb << 8);
4114 return 0;
4115 }
4116
4117 static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
4118 unsigned long arg)
4119 {
4120 int ret = 0;
4121 void __user *argp = (void __user *)arg;
4122 u8 val8;
4123 u16 val16;
4124 int value;
4125
4126 mutex_lock(&spic_dev.lock);
4127 switch (cmd) {
4128 case SONYPI_IOCGBRT:
4129 if (sony_bl_props.dev == NULL) {
4130 ret = -EIO;
4131 break;
4132 }
4133 if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL,
4134 &value)) {
4135 ret = -EIO;
4136 break;
4137 }
4138 val8 = ((value & 0xff) - 1) << 5;
4139 if (copy_to_user(argp, &val8, sizeof(val8)))
4140 ret = -EFAULT;
4141 break;
4142 case SONYPI_IOCSBRT:
4143 if (sony_bl_props.dev == NULL) {
4144 ret = -EIO;
4145 break;
4146 }
4147 if (copy_from_user(&val8, argp, sizeof(val8))) {
4148 ret = -EFAULT;
4149 break;
4150 }
4151 value = (val8 >> 5) + 1;
4152 if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value,
4153 NULL)) {
4154 ret = -EIO;
4155 break;
4156 }
4157
4158 sony_bl_props.dev->props.brightness =
4159 sony_backlight_get_brightness(sony_bl_props.dev);
4160 break;
4161 case SONYPI_IOCGBAT1CAP:
4162 if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
4163 ret = -EIO;
4164 break;
4165 }
4166 if (copy_to_user(argp, &val16, sizeof(val16)))
4167 ret = -EFAULT;
4168 break;
4169 case SONYPI_IOCGBAT1REM:
4170 if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
4171 ret = -EIO;
4172 break;
4173 }
4174 if (copy_to_user(argp, &val16, sizeof(val16)))
4175 ret = -EFAULT;
4176 break;
4177 case SONYPI_IOCGBAT2CAP:
4178 if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
4179 ret = -EIO;
4180 break;
4181 }
4182 if (copy_to_user(argp, &val16, sizeof(val16)))
4183 ret = -EFAULT;
4184 break;
4185 case SONYPI_IOCGBAT2REM:
4186 if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
4187 ret = -EIO;
4188 break;
4189 }
4190 if (copy_to_user(argp, &val16, sizeof(val16)))
4191 ret = -EFAULT;
4192 break;
4193 case SONYPI_IOCGBATFLAGS:
4194 if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
4195 ret = -EIO;
4196 break;
4197 }
4198 val8 &= 0x07;
4199 if (copy_to_user(argp, &val8, sizeof(val8)))
4200 ret = -EFAULT;
4201 break;
4202 case SONYPI_IOCGBLUE:
4203 val8 = spic_dev.bluetooth_power;
4204 if (copy_to_user(argp, &val8, sizeof(val8)))
4205 ret = -EFAULT;
4206 break;
4207 case SONYPI_IOCSBLUE:
4208 if (copy_from_user(&val8, argp, sizeof(val8))) {
4209 ret = -EFAULT;
4210 break;
4211 }
4212 __sony_pic_set_bluetoothpower(val8);
4213 break;
4214
4215 case SONYPI_IOCGFAN:
4216 if (sony_pic_get_fanspeed(&val8)) {
4217 ret = -EIO;
4218 break;
4219 }
4220 if (copy_to_user(argp, &val8, sizeof(val8)))
4221 ret = -EFAULT;
4222 break;
4223 case SONYPI_IOCSFAN:
4224 if (copy_from_user(&val8, argp, sizeof(val8))) {
4225 ret = -EFAULT;
4226 break;
4227 }
4228 if (sony_pic_set_fanspeed(val8))
4229 ret = -EIO;
4230 break;
4231
4232 case SONYPI_IOCGTEMP:
4233 if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
4234 ret = -EIO;
4235 break;
4236 }
4237 if (copy_to_user(argp, &val8, sizeof(val8)))
4238 ret = -EFAULT;
4239 break;
4240 default:
4241 ret = -EINVAL;
4242 }
4243 mutex_unlock(&spic_dev.lock);
4244 return ret;
4245 }
4246
4247 static const struct file_operations sonypi_misc_fops = {
4248 .owner = THIS_MODULE,
4249 .read = sonypi_misc_read,
4250 .poll = sonypi_misc_poll,
4251 .open = sonypi_misc_open,
4252 .release = sonypi_misc_release,
4253 .fasync = sonypi_misc_fasync,
4254 .unlocked_ioctl = sonypi_misc_ioctl,
4255 .llseek = noop_llseek,
4256 };
4257
4258 static struct miscdevice sonypi_misc_device = {
4259 .minor = MISC_DYNAMIC_MINOR,
4260 .name = "sonypi",
4261 .fops = &sonypi_misc_fops,
4262 };
4263
4264 static void sonypi_compat_report_event(u8 event)
4265 {
4266 kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event,
4267 sizeof(event), &sonypi_compat.fifo_lock);
4268 kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
4269 wake_up_interruptible(&sonypi_compat.fifo_proc_list);
4270 }
4271
4272 static int sonypi_compat_init(void)
4273 {
4274 int error;
4275
4276 spin_lock_init(&sonypi_compat.fifo_lock);
4277 error =
4278 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
4279 if (error) {
4280 pr_err("kfifo_alloc failed\n");
4281 return error;
4282 }
4283
4284 init_waitqueue_head(&sonypi_compat.fifo_proc_list);
4285
4286 if (minor != -1)
4287 sonypi_misc_device.minor = minor;
4288 error = misc_register(&sonypi_misc_device);
4289 if (error) {
4290 pr_err("misc_register failed\n");
4291 goto err_free_kfifo;
4292 }
4293 if (minor == -1)
4294 pr_info("device allocated minor is %d\n",
4295 sonypi_misc_device.minor);
4296
4297 return 0;
4298
4299 err_free_kfifo:
4300 kfifo_free(&sonypi_compat.fifo);
4301 return error;
4302 }
4303
4304 static void sonypi_compat_exit(void)
4305 {
4306 misc_deregister(&sonypi_misc_device);
4307 kfifo_free(&sonypi_compat.fifo);
4308 }
4309 #else
4310 static int sonypi_compat_init(void) { return 0; }
4311 static void sonypi_compat_exit(void) { }
4312 static void sonypi_compat_report_event(u8 event) { }
4313 #endif
4314
4315
4316
4317
4318 static acpi_status
4319 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
4320 {
4321 u32 i;
4322 struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
4323
4324 switch (resource->type) {
4325 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
4326 {
4327
4328 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
4329 if (!ioport)
4330 return AE_ERROR;
4331
4332 list_add(&ioport->list, &dev->ioports);
4333 return AE_OK;
4334 }
4335
4336 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
4337
4338 return AE_OK;
4339
4340 case ACPI_RESOURCE_TYPE_IRQ:
4341 {
4342 struct acpi_resource_irq *p = &resource->data.irq;
4343 struct sony_pic_irq *interrupt = NULL;
4344 if (!p->interrupt_count) {
4345
4346
4347
4348
4349 dprintk("Blank IRQ resource\n");
4350 return AE_OK;
4351 }
4352 for (i = 0; i < p->interrupt_count; i++) {
4353 if (!p->interrupts[i]) {
4354 pr_warn("Invalid IRQ %d\n",
4355 p->interrupts[i]);
4356 continue;
4357 }
4358 interrupt = kzalloc(sizeof(*interrupt),
4359 GFP_KERNEL);
4360 if (!interrupt)
4361 return AE_ERROR;
4362
4363 list_add(&interrupt->list, &dev->interrupts);
4364 interrupt->irq.triggering = p->triggering;
4365 interrupt->irq.polarity = p->polarity;
4366 interrupt->irq.shareable = p->shareable;
4367 interrupt->irq.interrupt_count = 1;
4368 interrupt->irq.interrupts[0] = p->interrupts[i];
4369 }
4370 return AE_OK;
4371 }
4372 case ACPI_RESOURCE_TYPE_IO:
4373 {
4374 struct acpi_resource_io *io = &resource->data.io;
4375 struct sony_pic_ioport *ioport =
4376 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
4377 if (!ioport->io1.minimum) {
4378 memcpy(&ioport->io1, io, sizeof(*io));
4379 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
4380 ioport->io1.address_length);
4381 }
4382 else if (!ioport->io2.minimum) {
4383 memcpy(&ioport->io2, io, sizeof(*io));
4384 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
4385 ioport->io2.address_length);
4386 }
4387 else {
4388 pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
4389 return AE_ERROR;
4390 }
4391 return AE_OK;
4392 }
4393
4394 case ACPI_RESOURCE_TYPE_END_TAG:
4395 return AE_OK;
4396
4397 default:
4398 dprintk("Resource %d isn't an IRQ nor an IO port\n",
4399 resource->type);
4400 return AE_CTRL_TERMINATE;
4401
4402 }
4403 }
4404
4405 static int sony_pic_possible_resources(struct acpi_device *device)
4406 {
4407 int result = 0;
4408 acpi_status status = AE_OK;
4409
4410 if (!device)
4411 return -EINVAL;
4412
4413
4414
4415 dprintk("Evaluating _STA\n");
4416 result = acpi_bus_get_status(device);
4417 if (result) {
4418 pr_warn("Unable to read status\n");
4419 goto end;
4420 }
4421
4422 if (!device->status.enabled)
4423 dprintk("Device disabled\n");
4424 else
4425 dprintk("Device enabled\n");
4426
4427
4428
4429
4430 dprintk("Evaluating %s\n", METHOD_NAME__PRS);
4431 status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
4432 sony_pic_read_possible_resource, &spic_dev);
4433 if (ACPI_FAILURE(status)) {
4434 pr_warn("Failure evaluating %s\n", METHOD_NAME__PRS);
4435 result = -ENODEV;
4436 }
4437 end:
4438 return result;
4439 }
4440
4441
4442
4443
4444 static int sony_pic_disable(struct acpi_device *device)
4445 {
4446 acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL,
4447 NULL);
4448
4449 if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND)
4450 return -ENXIO;
4451
4452 dprintk("Device disabled\n");
4453 return 0;
4454 }
4455
4456
4457
4458
4459
4460
4461
4462 static int sony_pic_enable(struct acpi_device *device,
4463 struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
4464 {
4465 acpi_status status;
4466 int result = 0;
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478 struct {
4479 struct acpi_resource res1;
4480 struct acpi_resource res2;
4481 struct acpi_resource res3;
4482 struct acpi_resource res4;
4483 } *resource;
4484 struct acpi_buffer buffer = { 0, NULL };
4485
4486 if (!ioport || !irq)
4487 return -EINVAL;
4488
4489
4490 resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
4491 if (!resource)
4492 return -ENOMEM;
4493
4494 buffer.length = sizeof(*resource) + 1;
4495 buffer.pointer = resource;
4496
4497
4498 if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
4499
4500
4501 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
4502 resource->res1.length = sizeof(struct acpi_resource);
4503 memcpy(&resource->res1.data.io, &ioport->io1,
4504 sizeof(struct acpi_resource_io));
4505
4506 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
4507 resource->res2.length = sizeof(struct acpi_resource);
4508 memcpy(&resource->res2.data.io, &ioport->io2,
4509 sizeof(struct acpi_resource_io));
4510
4511
4512 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
4513 resource->res3.length = sizeof(struct acpi_resource);
4514 memcpy(&resource->res3.data.irq, &irq->irq,
4515 sizeof(struct acpi_resource_irq));
4516
4517 resource->res3.data.irq.shareable = ACPI_SHARED;
4518
4519 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
4520 resource->res4.length = sizeof(struct acpi_resource);
4521 }
4522
4523 else {
4524
4525 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
4526 resource->res1.length = sizeof(struct acpi_resource);
4527 memcpy(&resource->res1.data.io, &ioport->io1,
4528 sizeof(struct acpi_resource_io));
4529
4530
4531 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
4532 resource->res2.length = sizeof(struct acpi_resource);
4533 memcpy(&resource->res2.data.irq, &irq->irq,
4534 sizeof(struct acpi_resource_irq));
4535
4536 resource->res2.data.irq.shareable = ACPI_SHARED;
4537
4538 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
4539 resource->res3.length = sizeof(struct acpi_resource);
4540 }
4541
4542
4543 dprintk("Evaluating _SRS\n");
4544 status = acpi_set_current_resources(device->handle, &buffer);
4545
4546
4547 if (ACPI_FAILURE(status)) {
4548 pr_err("Error evaluating _SRS\n");
4549 result = -ENODEV;
4550 goto end;
4551 }
4552
4553
4554 sony_pic_call1(0x82);
4555 sony_pic_call2(0x81, 0xff);
4556 sony_pic_call1(compat ? 0x92 : 0x82);
4557
4558 end:
4559 kfree(resource);
4560 return result;
4561 }
4562
4563
4564
4565
4566
4567
4568 static irqreturn_t sony_pic_irq(int irq, void *dev_id)
4569 {
4570 int i, j;
4571 u8 ev = 0;
4572 u8 data_mask = 0;
4573 u8 device_event = 0;
4574
4575 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
4576
4577 ev = inb_p(dev->cur_ioport->io1.minimum);
4578 if (dev->cur_ioport->io2.minimum)
4579 data_mask = inb_p(dev->cur_ioport->io2.minimum);
4580 else
4581 data_mask = inb_p(dev->cur_ioport->io1.minimum +
4582 dev->evport_offset);
4583
4584 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4585 ev, data_mask, dev->cur_ioport->io1.minimum,
4586 dev->evport_offset);
4587
4588 if (ev == 0x00 || ev == 0xff)
4589 return IRQ_HANDLED;
4590
4591 for (i = 0; dev->event_types[i].mask; i++) {
4592
4593 if ((data_mask & dev->event_types[i].data) !=
4594 dev->event_types[i].data)
4595 continue;
4596
4597 if (!(mask & dev->event_types[i].mask))
4598 continue;
4599
4600 for (j = 0; dev->event_types[i].events[j].event; j++) {
4601 if (ev == dev->event_types[i].events[j].data) {
4602 device_event =
4603 dev->event_types[i].events[j].event;
4604
4605 if (!device_event)
4606 return IRQ_HANDLED;
4607 goto found;
4608 }
4609 }
4610 }
4611
4612
4613
4614 if (dev->handle_irq && dev->handle_irq(data_mask, ev) == 0)
4615 return IRQ_HANDLED;
4616
4617 dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4618 ev, data_mask, dev->cur_ioport->io1.minimum,
4619 dev->evport_offset);
4620 return IRQ_HANDLED;
4621
4622 found:
4623 sony_laptop_report_input_event(device_event);
4624 sonypi_compat_report_event(device_event);
4625 return IRQ_HANDLED;
4626 }
4627
4628
4629
4630
4631
4632
4633 static int sony_pic_remove(struct acpi_device *device)
4634 {
4635 struct sony_pic_ioport *io, *tmp_io;
4636 struct sony_pic_irq *irq, *tmp_irq;
4637
4638 if (sony_pic_disable(device)) {
4639 pr_err("Couldn't disable device\n");
4640 return -ENXIO;
4641 }
4642
4643 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4644 release_region(spic_dev.cur_ioport->io1.minimum,
4645 spic_dev.cur_ioport->io1.address_length);
4646 if (spic_dev.cur_ioport->io2.minimum)
4647 release_region(spic_dev.cur_ioport->io2.minimum,
4648 spic_dev.cur_ioport->io2.address_length);
4649
4650 sonypi_compat_exit();
4651
4652 sony_laptop_remove_input();
4653
4654
4655 sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4656 sony_pf_remove();
4657
4658 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4659 list_del(&io->list);
4660 kfree(io);
4661 }
4662 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4663 list_del(&irq->list);
4664 kfree(irq);
4665 }
4666 spic_dev.cur_ioport = NULL;
4667 spic_dev.cur_irq = NULL;
4668
4669 dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
4670 return 0;
4671 }
4672
4673 static int sony_pic_add(struct acpi_device *device)
4674 {
4675 int result;
4676 struct sony_pic_ioport *io, *tmp_io;
4677 struct sony_pic_irq *irq, *tmp_irq;
4678
4679 spic_dev.acpi_dev = device;
4680 strcpy(acpi_device_class(device), "sony/hotkey");
4681 sony_pic_detect_device_type(&spic_dev);
4682 mutex_init(&spic_dev.lock);
4683
4684
4685 result = sony_pic_possible_resources(device);
4686 if (result) {
4687 pr_err("Unable to read possible resources\n");
4688 goto err_free_resources;
4689 }
4690
4691
4692 result = sony_laptop_setup_input(device);
4693 if (result) {
4694 pr_err("Unable to create input devices\n");
4695 goto err_free_resources;
4696 }
4697
4698 result = sonypi_compat_init();
4699 if (result)
4700 goto err_remove_input;
4701
4702
4703 list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
4704 if (request_region(io->io1.minimum, io->io1.address_length,
4705 "Sony Programmable I/O Device")) {
4706 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
4707 io->io1.minimum, io->io1.maximum,
4708 io->io1.address_length);
4709
4710 if (io->io2.minimum) {
4711 if (request_region(io->io2.minimum,
4712 io->io2.address_length,
4713 "Sony Programmable I/O Device")) {
4714 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
4715 io->io2.minimum, io->io2.maximum,
4716 io->io2.address_length);
4717 spic_dev.cur_ioport = io;
4718 break;
4719 }
4720 else {
4721 dprintk("Unable to get I/O port2: "
4722 "0x%.4x (0x%.4x) + 0x%.2x\n",
4723 io->io2.minimum, io->io2.maximum,
4724 io->io2.address_length);
4725 release_region(io->io1.minimum,
4726 io->io1.address_length);
4727 }
4728 }
4729 else {
4730 spic_dev.cur_ioport = io;
4731 break;
4732 }
4733 }
4734 }
4735 if (!spic_dev.cur_ioport) {
4736 pr_err("Failed to request_region\n");
4737 result = -ENODEV;
4738 goto err_remove_compat;
4739 }
4740
4741
4742 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
4743 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
4744 0, "sony-laptop", &spic_dev)) {
4745 dprintk("IRQ: %d - triggering: %d - "
4746 "polarity: %d - shr: %d\n",
4747 irq->irq.interrupts[0],
4748 irq->irq.triggering,
4749 irq->irq.polarity,
4750 irq->irq.shareable);
4751 spic_dev.cur_irq = irq;
4752 break;
4753 }
4754 }
4755 if (!spic_dev.cur_irq) {
4756 pr_err("Failed to request_irq\n");
4757 result = -ENODEV;
4758 goto err_release_region;
4759 }
4760
4761
4762 result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
4763 if (result) {
4764 pr_err("Couldn't enable device\n");
4765 goto err_free_irq;
4766 }
4767
4768 spic_dev.bluetooth_power = -1;
4769
4770 result = sony_pf_add();
4771 if (result)
4772 goto err_disable_device;
4773
4774 result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
4775 if (result)
4776 goto err_remove_pf;
4777
4778 pr_info("SPIC setup done.\n");
4779 return 0;
4780
4781 err_remove_pf:
4782 sony_pf_remove();
4783
4784 err_disable_device:
4785 sony_pic_disable(device);
4786
4787 err_free_irq:
4788 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
4789
4790 err_release_region:
4791 release_region(spic_dev.cur_ioport->io1.minimum,
4792 spic_dev.cur_ioport->io1.address_length);
4793 if (spic_dev.cur_ioport->io2.minimum)
4794 release_region(spic_dev.cur_ioport->io2.minimum,
4795 spic_dev.cur_ioport->io2.address_length);
4796
4797 err_remove_compat:
4798 sonypi_compat_exit();
4799
4800 err_remove_input:
4801 sony_laptop_remove_input();
4802
4803 err_free_resources:
4804 list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
4805 list_del(&io->list);
4806 kfree(io);
4807 }
4808 list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
4809 list_del(&irq->list);
4810 kfree(irq);
4811 }
4812 spic_dev.cur_ioport = NULL;
4813 spic_dev.cur_irq = NULL;
4814
4815 return result;
4816 }
4817
4818 #ifdef CONFIG_PM_SLEEP
4819 static int sony_pic_suspend(struct device *dev)
4820 {
4821 if (sony_pic_disable(to_acpi_device(dev)))
4822 return -ENXIO;
4823 return 0;
4824 }
4825
4826 static int sony_pic_resume(struct device *dev)
4827 {
4828 sony_pic_enable(to_acpi_device(dev),
4829 spic_dev.cur_ioport, spic_dev.cur_irq);
4830 return 0;
4831 }
4832 #endif
4833
4834 static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
4835
4836 static const struct acpi_device_id sony_pic_device_ids[] = {
4837 {SONY_PIC_HID, 0},
4838 {"", 0},
4839 };
4840
4841 static struct acpi_driver sony_pic_driver = {
4842 .name = SONY_PIC_DRIVER_NAME,
4843 .class = SONY_PIC_CLASS,
4844 .ids = sony_pic_device_ids,
4845 .owner = THIS_MODULE,
4846 .ops = {
4847 .add = sony_pic_add,
4848 .remove = sony_pic_remove,
4849 },
4850 .drv.pm = &sony_pic_pm,
4851 };
4852
4853 static const struct dmi_system_id sonypi_dmi_table[] __initconst = {
4854 {
4855 .ident = "Sony Vaio",
4856 .matches = {
4857 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4858 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
4859 },
4860 },
4861 {
4862 .ident = "Sony Vaio",
4863 .matches = {
4864 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
4865 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
4866 },
4867 },
4868 { }
4869 };
4870
4871 static int __init sony_laptop_init(void)
4872 {
4873 int result;
4874
4875 if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
4876 result = acpi_bus_register_driver(&sony_pic_driver);
4877 if (result) {
4878 pr_err("Unable to register SPIC driver\n");
4879 goto out;
4880 }
4881 spic_drv_registered = 1;
4882 }
4883
4884 result = acpi_bus_register_driver(&sony_nc_driver);
4885 if (result) {
4886 pr_err("Unable to register SNC driver\n");
4887 goto out_unregister_pic;
4888 }
4889
4890 return 0;
4891
4892 out_unregister_pic:
4893 if (spic_drv_registered)
4894 acpi_bus_unregister_driver(&sony_pic_driver);
4895 out:
4896 return result;
4897 }
4898
4899 static void __exit sony_laptop_exit(void)
4900 {
4901 acpi_bus_unregister_driver(&sony_nc_driver);
4902 if (spic_drv_registered)
4903 acpi_bus_unregister_driver(&sony_pic_driver);
4904 }
4905
4906 module_init(sony_laptop_init);
4907 module_exit(sony_laptop_exit);