45 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
47 #include <linux/kernel.h>
48 #include <linux/module.h>
51 #include <linux/types.h>
56 #include <linux/pci.h>
59 #include <linux/input.h>
63 #include <linux/slab.h>
66 #include <asm/uaccess.h>
67 #include <linux/sonypi.h>
69 #include <linux/rfkill.h>
70 #ifdef CONFIG_SONYPI_COMPAT
71 #include <linux/poll.h>
75 #define dprintk(fmt, ...) \
78 pr_warn(fmt, ##__VA_ARGS__); \
81 #define SONY_LAPTOP_DRIVER_VERSION "0.6"
83 #define SONY_NC_CLASS "sony-nc"
84 #define SONY_NC_HID "SNY5001"
85 #define SONY_NC_DRIVER_NAME "Sony Notebook Control Driver"
87 #define SONY_PIC_CLASS "sony-pic"
88 #define SONY_PIC_HID "SNY6001"
89 #define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"
99 "the development of this driver");
104 "set this if you don't want to enable the SPIC device");
109 "set this if you want to enable backward compatibility mode");
111 static unsigned long mask = 0xffffffff;
114 "set this to the mask of event you want to enable (see doc)");
119 "set this to 1 to enable Motion Eye camera controls "
120 "(only use it if you have a C1VE or C1VN model)");
122 #ifdef CONFIG_SONYPI_COMPAT
123 static int minor = -1;
126 "minor number of the misc device for the SPIC compatibility code, "
127 "default is -1 (automatic)");
133 "set this to 0 to disable keyboard backlight, "
134 "1 to enable it (default: 0)");
136 static int kbd_backlight_timeout;
139 "set this to 0 to set the default 10 seconds timeout, "
140 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
143 #ifdef CONFIG_PM_SLEEP
144 static void sony_nc_kbd_backlight_resume(
void);
145 static void sony_nc_thermal_resume(
void);
161 static int sony_nc_highspeed_charging_setup(
struct platform_device *pd);
162 static void sony_nc_highspeed_charging_cleanup(
struct platform_device *pd);
176 static int sony_rfkill_handle;
178 static int sony_rfkill_address[
N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
179 static int sony_nc_rfkill_setup(
struct acpi_device *
device,
181 static void sony_nc_rfkill_cleanup(
void);
182 static void sony_nc_rfkill_update(
void);
186 #define SONY_LAPTOP_BUF_SIZE 128
208 static int sony_laptop_input_index[] = {
285 static int sony_laptop_input_keycode_map[] = {
349 static void do_sony_laptop_release_key(
unsigned long unused)
357 (
unsigned char *)&kp,
sizeof(kp)) ==
sizeof(kp)) {
358 input_report_key(kp.dev, kp.key, 0);
367 spin_unlock_irqrestore(&sony_laptop_input.
fifo_lock, flags);
371 static void sony_laptop_report_input_event(
u8 event)
373 struct input_dev *jog_dev = sony_laptop_input.
jog_dev;
374 struct input_dev *key_dev = sony_laptop_input.
key_dev;
395 input_report_rel(jog_dev,
REL_WHEEL, -1);
406 if (event >=
ARRAY_SIZE(sony_laptop_input_index)) {
407 dprintk(
"sony_laptop_report_input_event, event not known: %d\n", event);
410 if ((scancode = sony_laptop_input_index[event]) != -1) {
411 kp.
key = sony_laptop_input_keycode_map[scancode];
423 input_report_key(kp.
dev, kp.
key, 1);
428 (
unsigned char *)&kp,
sizeof(kp),
433 dprintk(
"unknown input event %.2x\n", event);
436 static int sony_laptop_setup_input(
struct acpi_device *acpi_device)
438 struct input_dev *jog_dev;
439 struct input_dev *key_dev;
452 pr_err(
"kfifo_alloc failed\n");
457 do_sony_laptop_release_key, 0);
460 key_dev = input_allocate_device();
466 key_dev->name =
"Sony Vaio Keys";
469 key_dev->dev.parent = &acpi_device->dev;
475 key_dev->keycodesize =
sizeof(sony_laptop_input_keycode_map[0]);
476 key_dev->keycodemax =
ARRAY_SIZE(sony_laptop_input_keycode_map);
477 key_dev->keycode = &sony_laptop_input_keycode_map;
478 for (i = 0; i <
ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
479 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
482 error = input_register_device(key_dev);
484 goto err_free_keydev;
486 sony_laptop_input.
key_dev = key_dev;
489 jog_dev = input_allocate_device();
492 goto err_unregister_keydev;
495 jog_dev->name =
"Sony Vaio Jogdial";
498 jog_dev->dev.parent = &acpi_device->dev;
503 error = input_register_device(jog_dev);
505 goto err_free_jogdev;
507 sony_laptop_input.
jog_dev = jog_dev;
512 input_free_device(jog_dev);
514 err_unregister_keydev:
515 input_unregister_device(key_dev);
520 input_free_device(key_dev);
530 static void sony_laptop_remove_input(
void)
545 (
unsigned char *)&kp,
sizeof(kp)) ==
sizeof(kp)) {
546 input_report_key(kp.
dev, kp.
key, 0);
551 input_unregister_device(sony_laptop_input.
key_dev);
554 if (sony_laptop_input.
jog_dev) {
555 input_unregister_device(sony_laptop_input.
jog_dev);
567 .name =
"sony-laptop",
573 static int sony_pf_add(
void)
586 if (!sony_pf_device) {
588 goto out_platform_registered;
593 goto out_platform_alloced;
597 out_platform_alloced:
599 sony_pf_device =
NULL;
600 out_platform_registered:
607 static void sony_pf_remove(
void)
621 #define SONY_MAX_BRIGHTNESS 8
623 #define SNC_VALIDATE_IN 0
624 #define SNC_VALIDATE_OUT 1
629 const char *,
size_t);
630 static int boolean_validate(
const int,
const int);
631 static int brightness_default_validate(
const int,
const int);
644 #define SNC_HANDLE_NAMES(_name, _values...) \
645 static char *snc_##_name[] = { _values, NULL }
647 #define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
649 .name = __stringify(_name), \
650 .acpiget = _getters, \
651 .acpiset = _setters, \
652 .validate = _validate, \
654 .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
657 #define SNC_HANDLE_NULL { .name = NULL }
693 SNC_HANDLE(brightness_default, snc_brightness_def_get,
694 snc_brightness_def_set, brightness_default_validate, 0),
696 SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
697 SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
698 boolean_validate, 0),
699 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
700 boolean_validate, 1),
702 boolean_validate, 0),
703 SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set,
704 boolean_validate, 0),
705 SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set,
706 boolean_validate, 0),
716 static struct acpi_device *sony_nc_acpi_device =
NULL;
738 dprintk(
"__call_snc_method: [%s:0x%.8x%.8x]\n", method,
739 (
unsigned int)(*value >> 32),
740 (
unsigned int)*value & 0xffffffff);
743 dprintk(
"__call_snc_method: [%s]\n", method);
747 pr_err(
"Failed to evaluate [%s]\n", method);
753 dprintk(
"No return object [%s]\n", method);
758 static int sony_nc_int_call(
acpi_handle handle,
char *
name,
int *value,
764 object = __call_snc_method(handle, name, &v);
766 object = __call_snc_method(handle, name,
NULL);
772 pr_warn(
"Invalid acpi_object: expected 0x%x got 0x%x\n",
779 *result =
object->integer.value;
785 #define MIN(a, b) (a > b ? b : a)
786 static int sony_nc_buffer_call(
acpi_handle handle,
char *name,
u64 *value,
790 union acpi_object *
object = __call_snc_method(handle, name, value);
796 len =
MIN(buflen, object->
buffer.length);
799 len =
MIN(buflen,
sizeof(object->
integer.value));
802 pr_warn(
"Invalid acpi_object: expected 0x%x got 0x%x\n",
839 handles = kzalloc(
sizeof(*handles),
GFP_KERNEL);
845 r = sony_nc_int_call(sony_nc_acpi_handle,
"SN00", &arg,
848 dprintk(
"caching handle 0x%.4x (offset: 0x%.2x)\n",
856 handles->
devattr.attr.name =
"handles";
858 handles->
devattr.show = sony_nc_handles_show;
882 static int sony_find_snc_handle(
int handle)
887 if (!handles || !handle)
890 for (i = 0; i < 0x10; i++) {
891 if (handles->
cap[i] == handle) {
892 dprintk(
"found handle 0x%.4x (offset: 0x%.2x)\n",
897 dprintk(
"handle 0x%.4x not found\n", handle);
901 static int sony_call_snc_handle(
int handle,
int argument,
int *result)
904 int offset = sony_find_snc_handle(handle);
909 arg = offset | argument;
910 ret = sony_nc_int_call(sony_nc_acpi_handle,
"SN07", &arg, result);
911 dprintk(
"called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result);
924 static int brightness_default_validate(
const int direction,
const int value)
941 static int boolean_validate(
const int direction,
const int value)
944 if (value != 0 && value != 1)
963 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->
acpiget,
NULL,
976 const char *buffer,
size_t count)
998 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->
acpiset,
1023 int arg = bd->
props.brightness + 1;
1024 return sony_nc_int_call(sony_nc_acpi_handle,
"SBRT", &arg,
NULL);
1031 if (sony_nc_int_call(sony_nc_acpi_handle,
"GBRT",
NULL, &value))
1043 sony_call_snc_handle(sdev->
handle, sdev->
cmd_base + 0x100, &result);
1045 return (result & 0xff) - sdev->
offset;
1055 if (sony_call_snc_handle(sdev->
handle, sdev->
cmd_base | (value << 0x10),
1064 .update_status = sony_backlight_update_status,
1065 .get_brightness = sony_backlight_get_brightness,
1069 .update_status = sony_nc_update_status_ng,
1070 .get_brightness = sony_nc_get_brightness_ng,
1143 static int sony_nc_hotkeys_decode(
u32 event,
unsigned int handle)
1146 unsigned int result = 0;
1149 if (sony_call_snc_handle(handle, 0x200, &result)) {
1150 dprintk(
"Unable to decode event 0x%.2x 0x%.2x\n", handle,
1157 if (handle == 0x0100)
1158 key_event = sony_100_events;
1160 key_event = sony_127_events;
1162 for (; key_event->
data; key_event++) {
1163 if (key_event->
data == result) {
1164 ret = key_event->
event;
1169 if (!key_event->
data)
1170 pr_info(
"Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n",
1171 event, result, handle);
1184 static void sony_nc_notify(
struct acpi_device *
device,
u32 event)
1188 dprintk(
"sony_nc_notify, event: 0x%.2x\n", event);
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;
1197 pr_err(
"Event 0x%x outside of capabilities list\n",
1209 real_ev = sony_nc_hotkeys_decode(event, handle);
1212 sony_laptop_report_input_event(real_ev);
1229 sony_call_snc_handle(handle, 0x0100, &result);
1230 real_ev = result & 0x03;
1234 sony_nc_rfkill_update();
1241 sony_call_snc_handle(handle, 0x0000, &result);
1242 dprintk(
"GFX switch event received (reason: %s)\n",
1244 "switch change" :
"unknown");
1250 sony_call_snc_handle(handle, 0x0100, &result);
1253 real_ev = result & 0xff;
1257 dprintk(
"Unknown event 0x%x for handle 0x%x\n",
1264 sony_nc_int_call(sony_nc_acpi_handle,
"SN05", &arg, &result);
1269 sony_laptop_report_input_event(real_ev);
1272 acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev);
1275 dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev);
1284 pr_warn(
"method: name: %4.4s, args %X\n",
1296 static void sony_nc_function_setup(
struct acpi_device *device,
1306 unsigned int handle = handles->
cap[
i];
1311 dprintk(
"setting up handle 0x%.4x\n", handle);
1318 sony_call_snc_handle(handle, 0, &result);
1322 sony_call_snc_handle(handle, 0x100, &result);
1327 result = sony_nc_touchpad_setup(pf_device, handle);
1329 pr_err(
"couldn't set up touchpad control function (%d)\n",
1335 result = sony_nc_battery_care_setup(pf_device, handle);
1337 pr_err(
"couldn't set up battery care function (%d)\n",
1341 result = sony_nc_lid_resume_setup(pf_device);
1343 pr_err(
"couldn't set up lid resume function (%d)\n",
1347 result = sony_nc_thermal_setup(pf_device);
1349 pr_err(
"couldn't set up thermal profile function (%d)\n",
1353 result = sony_nc_highspeed_charging_setup(pf_device);
1355 pr_err(
"couldn't set up high speed charging function (%d)\n",
1360 result = sony_nc_rfkill_setup(device, handle);
1362 pr_err(
"couldn't set up rfkill support (%d)\n",
1367 result = sony_nc_kbd_backlight_setup(pf_device, handle);
1369 pr_err(
"couldn't set up keyboard backlight function (%d)\n",
1379 if (!sony_nc_int_call(sony_nc_acpi_handle,
"SN00", &arg, &bitmask))
1380 sony_nc_int_call(sony_nc_acpi_handle,
"SN02", &bitmask,
1389 sony_nc_int_call(sony_nc_acpi_handle,
"SN01",
NULL, &bitmask);
1390 sony_nc_int_call(sony_nc_acpi_handle,
"SN03", &bitmask, &result);
1395 handle = handles->
cap[
i];
1403 sony_nc_touchpad_cleanup(pd);
1408 sony_nc_battery_care_cleanup(pd);
1411 sony_nc_lid_resume_cleanup(pd);
1414 sony_nc_thermal_cleanup(pd);
1417 sony_nc_highspeed_charging_cleanup(pd);
1421 sony_nc_rfkill_cleanup();
1425 sony_nc_kbd_backlight_cleanup(pd);
1433 sony_nc_handles_cleanup(pd);
1436 #ifdef CONFIG_PM_SLEEP
1437 static void sony_nc_function_resume(
void)
1441 dprintk(
"Resuming SNC device\n");
1444 unsigned int handle = handles->
cap[
i];
1454 sony_call_snc_handle(handle, 0, &result);
1458 sony_call_snc_handle(handle, 0x100, &result);
1461 sony_nc_thermal_resume();
1465 sony_nc_rfkill_update();
1469 sony_nc_kbd_backlight_resume();
1478 if (!sony_nc_int_call(sony_nc_acpi_handle,
"SN00", &arg, &bitmask))
1479 sony_nc_int_call(sony_nc_acpi_handle,
"SN02", &bitmask,
1483 static int sony_nc_resume(
struct device *dev)
1488 for (item = sony_nc_values; item->
name; item++) {
1493 ret = sony_nc_int_call(sony_nc_acpi_handle, *item->
acpiset,
1496 pr_err(
"%s: %d\n", __func__, ret);
1504 if (sony_nc_int_call(sony_nc_acpi_handle,
"ECON", &arg,
NULL))
1505 dprintk(
"ECON Method failed\n");
1510 sony_nc_function_resume();
1518 static void sony_nc_rfkill_cleanup(
void)
1523 if (sony_rfkill_devices[i]) {
1530 static int sony_nc_rfkill_set(
void *
data,
bool blocked)
1533 int argument = sony_rfkill_address[(
long) data] + 0x100;
1536 argument |= 0x030000;
1538 return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1541 static const struct rfkill_ops sony_rfkill_ops = {
1542 .set_block = sony_nc_rfkill_set,
1545 static int sony_nc_setup_rfkill(
struct acpi_device *device,
1553 bool hwblock, swblock;
1562 name =
"sony-bluetooth";
1570 name =
"sony-wimax";
1577 &sony_rfkill_ops, (
void *)nc_type);
1581 if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) {
1585 hwblock = !(result & 0x1);
1587 if (sony_call_snc_handle(sony_rfkill_handle,
1588 sony_rfkill_address[nc_type],
1593 swblock = !(result & 0x2);
1603 sony_rfkill_devices[nc_type] = rfk;
1607 static void sony_nc_rfkill_update(
void)
1613 sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1614 hwblock = !(result & 0x1);
1617 int argument = sony_rfkill_address[
i];
1619 if (!sony_rfkill_devices[i])
1629 sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1631 !(result & 0x2),
false);
1635 static int sony_nc_rfkill_setup(
struct acpi_device *device,
1636 unsigned int handle)
1640 unsigned char buffer[32] = { 0 };
1642 offset = sony_find_snc_handle(handle);
1643 sony_rfkill_handle =
handle;
1645 i = sony_nc_buffer_call(sony_nc_acpi_handle,
"SN06", &offset, buffer,
1671 if (buffer[i] == 0xff)
1674 dprintk(
"Radio devices, found 0x%.2x\n", buffer[i]);
1676 if (buffer[i] == 0 && !sony_rfkill_devices[
SONY_WIFI])
1677 sony_nc_setup_rfkill(device, SONY_WIFI);
1680 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1682 if (((0xf0 & buffer[i]) == 0x20 ||
1683 (0xf0 & buffer[i]) == 0x50) &&
1685 sony_nc_setup_rfkill(device, SONY_WWAN);
1687 if (buffer[i] == 0x30 && !sony_rfkill_devices[
SONY_WIMAX])
1688 sony_nc_setup_rfkill(device, SONY_WIMAX);
1705 static ssize_t __sony_nc_kbd_backlight_mode_set(
u8 value)
1712 if (sony_call_snc_handle(kbdbl_ctl->
handle,
1713 (value << 0x10) | (kbdbl_ctl->
base), &result))
1717 sony_call_snc_handle(kbdbl_ctl->
handle,
1718 (value << 0x10) | (kbdbl_ctl->
base + 0x100), &result);
1725 static ssize_t sony_nc_kbd_backlight_mode_store(
struct device *dev,
1727 const char *buffer,
size_t count)
1730 unsigned long value;
1735 if (kstrtoul(buffer, 10, &value))
1738 ret = __sony_nc_kbd_backlight_mode_set(value);
1745 static ssize_t sony_nc_kbd_backlight_mode_show(
struct device *dev,
1753 static int __sony_nc_kbd_backlight_timeout_set(
u8 value)
1760 if (sony_call_snc_handle(kbdbl_ctl->
handle, (value << 0x10) |
1761 (kbdbl_ctl->
base + 0x200), &result))
1769 static ssize_t sony_nc_kbd_backlight_timeout_store(
struct device *dev,
1771 const char *buffer,
size_t count)
1774 unsigned long value;
1779 if (kstrtoul(buffer, 10, &value))
1782 ret = __sony_nc_kbd_backlight_timeout_set(value);
1789 static ssize_t sony_nc_kbd_backlight_timeout_show(
struct device *dev,
1798 unsigned int handle)
1806 ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100,
1811 if ((handle == 0x0137 && !(result & 0x02)) ||
1813 dprintk(
"no backlight keyboard found\n");
1817 kbdbl_ctl = kzalloc(
sizeof(*kbdbl_ctl),
GFP_KERNEL);
1822 if (handle == 0x0137)
1823 kbdbl_ctl->
base = 0x0C00;
1825 kbdbl_ctl->
base = 0x4000;
1828 kbdbl_ctl->
mode_attr.attr.name =
"kbd_backlight";
1830 kbdbl_ctl->
mode_attr.show = sony_nc_kbd_backlight_mode_show;
1831 kbdbl_ctl->
mode_attr.store = sony_nc_kbd_backlight_mode_store;
1834 kbdbl_ctl->
timeout_attr.attr.name =
"kbd_backlight_timeout";
1836 kbdbl_ctl->
timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1837 kbdbl_ctl->
timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1848 __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
1869 sony_call_snc_handle(kbdbl_ctl->
handle,
1870 kbdbl_ctl->
base | 0x10000, &result);
1871 sony_call_snc_handle(kbdbl_ctl->
handle,
1872 kbdbl_ctl->
base + 0x200, &result);
1879 #ifdef CONFIG_PM_SLEEP
1880 static void sony_nc_kbd_backlight_resume(
void)
1887 if (kbdbl_ctl->
mode == 0)
1888 sony_call_snc_handle(kbdbl_ctl->
handle, kbdbl_ctl->
base,
1892 sony_call_snc_handle(kbdbl_ctl->
handle,
1893 (kbdbl_ctl->
base + 0x200) |
1894 (kbdbl_ctl->
timeout << 0x10), &ignore);
1904 static ssize_t sony_nc_battery_care_limit_store(
struct device *dev,
1906 const char *buffer,
size_t count)
1909 unsigned long value;
1914 if (kstrtoul(buffer, 10, &value))
1935 else if (value <= 80)
1938 else if (value <= 100)
1949 if (bcare_ctl->
handle != 0x013f)
1950 cmd = cmd | (cmd << 2);
1952 cmd = (cmd | 0x1) << 0x10;
1955 if (sony_call_snc_handle(bcare_ctl->
handle, cmd | 0x0100, &result))
1961 static ssize_t sony_nc_battery_care_limit_show(
struct device *dev,
1966 if (sony_call_snc_handle(bcare_ctl->
handle, 0x0000, &result))
1969 status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0;
1988 static ssize_t sony_nc_battery_care_health_show(
struct device *dev,
1992 unsigned int health;
1994 if (sony_call_snc_handle(bcare_ctl->
handle, 0x0200, &health))
2003 unsigned int handle)
2014 bcare_ctl->
attrs[0].attr.name =
"battery_care_limiter";
2016 bcare_ctl->
attrs[0].show = sony_nc_battery_care_limit_show;
2017 bcare_ctl->
attrs[0].store = sony_nc_battery_care_limit_store;
2024 if (handle == 0x0115)
2028 bcare_ctl->
attrs[1].attr.name =
"battery_care_health";
2030 bcare_ctl->
attrs[1].show = sony_nc_battery_care_health_show;
2052 if (bcare_ctl->
handle != 0x0115)
2068 #define THM_PROFILE_MAX 3
2069 static const char *
const snc_thermal_profiles[] = {
2075 static int sony_nc_thermal_mode_set(
unsigned short mode)
2088 if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result))
2096 static int sony_nc_thermal_mode_get(
void)
2100 if (sony_call_snc_handle(0x0122, 0x0100, &result))
2103 return result & 0xff;
2106 static ssize_t sony_nc_thermal_profiles_show(
struct device *dev,
2113 if (!cnt || (th_handle->
profiles & cnt))
2115 snc_thermal_profiles[cnt]);
2122 static ssize_t sony_nc_thermal_mode_store(
struct device *dev,
2124 const char *buffer,
size_t count)
2133 if (buffer[len - 1] ==
'\n')
2137 if (
strncmp(buffer, snc_thermal_profiles[cmd], len) == 0)
2140 if (sony_nc_thermal_mode_set(cmd))
2146 static ssize_t sony_nc_thermal_mode_show(
struct device *dev,
2150 int mode = sony_nc_thermal_mode_get();
2167 ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->
profiles);
2169 pr_warn(
"couldn't to read the thermal profiles\n");
2173 ret = sony_nc_thermal_mode_get();
2175 pr_warn(
"couldn't to read the current thermal profile");
2183 th_handle->
profiles_attr.show = sony_nc_thermal_profiles_show;
2186 th_handle->
mode_attr.attr.name =
"thermal_control";
2188 th_handle->
mode_attr.show = sony_nc_thermal_mode_show;
2189 th_handle->
mode_attr.store = sony_nc_thermal_mode_store;
2219 #ifdef CONFIG_PM_SLEEP
2220 static void sony_nc_thermal_resume(
void)
2222 unsigned int status = sony_nc_thermal_mode_get();
2224 if (status != th_handle->
mode)
2225 sony_nc_thermal_mode_set(th_handle->
mode);
2236 static ssize_t sony_nc_lid_resume_store(
struct device *dev,
2238 const char *buffer,
size_t count)
2241 unsigned long value;
2245 if (kstrtoul(buffer, 10, &value) || value > 1)
2254 if (
strcmp(attr->
attr.name,
"lid_resume_S3") == 0)
2256 else if (
strcmp(attr->
attr.name,
"lid_resume_S4") == 0)
2258 else if (
strcmp(attr->
attr.name,
"lid_resume_S5") == 0)
2268 if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result))
2276 static ssize_t sony_nc_lid_resume_show(
struct device *dev,
2281 if (
strcmp(attr->
attr.name,
"lid_resume_S3") == 0)
2283 else if (
strcmp(attr->
attr.name,
"lid_resume_S4") == 0)
2285 else if (
strcmp(attr->
attr.name,
"lid_resume_S5") == 0)
2291 (lid_ctl->
status >> pos) & 0x01);
2299 if (sony_call_snc_handle(0x0119, 0x0000, &result))
2306 lid_ctl->
status = result & 0x7;
2309 lid_ctl->
attrs[0].attr.name =
"lid_resume_S3";
2311 lid_ctl->
attrs[0].show = sony_nc_lid_resume_show;
2312 lid_ctl->
attrs[0].store = sony_nc_lid_resume_store;
2315 lid_ctl->
attrs[1].attr.name =
"lid_resume_S4";
2317 lid_ctl->
attrs[1].show = sony_nc_lid_resume_show;
2318 lid_ctl->
attrs[1].store = sony_nc_lid_resume_store;
2321 lid_ctl->
attrs[2].attr.name =
"lid_resume_S5";
2323 lid_ctl->
attrs[2].show = sony_nc_lid_resume_show;
2324 lid_ctl->
attrs[2].store = sony_nc_lid_resume_store;
2326 for (i = 0; i < 3; i++) {
2349 for (i = 0; i < 3; i++)
2360 static ssize_t sony_nc_highspeed_charging_store(
struct device *dev,
2362 const char *buffer,
size_t count)
2365 unsigned long value;
2370 if (kstrtoul(buffer, 10, &value) || value > 1)
2373 if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result))
2379 static ssize_t sony_nc_highspeed_charging_show(
struct device *dev,
2384 if (sony_call_snc_handle(0x0131, 0x0100, &result))
2390 static int sony_nc_highspeed_charging_setup(
struct platform_device *pd)
2394 if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) {
2398 pr_info(
"No High Speed Charging capability found\n");
2407 hsc_handle->
attr.name =
"battery_highspeed_charging";
2409 hsc_handle->
show = sony_nc_highspeed_charging_show;
2410 hsc_handle->
store = sony_nc_highspeed_charging_store;
2422 static void sony_nc_highspeed_charging_cleanup(
struct platform_device *pd)
2438 static ssize_t sony_nc_touchpad_store(
struct device *dev,
2442 unsigned long value;
2447 if (kstrtoul(buffer, 10, &value) || value > 1)
2453 if (sony_call_snc_handle(tp_ctl->
handle,
2454 (!value << 0x10) | 0x100, &result))
2460 static ssize_t sony_nc_touchpad_show(
struct device *dev,
2465 if (sony_call_snc_handle(tp_ctl->
handle, 0x000, &result))
2472 unsigned int handle)
2483 tp_ctl->
attr.attr.name =
"touchpad";
2485 tp_ctl->
attr.show = sony_nc_touchpad_show;
2486 tp_ctl->
attr.store = sony_nc_touchpad_store;
2506 static void sony_nc_backlight_ng_read_limits(
int handle,
2511 int lvl_table_len = 0;
2513 unsigned char buffer[32] = { 0 };
2519 offset = sony_find_snc_handle(handle);
2524 i = sony_nc_buffer_call(sony_nc_acpi_handle,
"SN06", &offset, buffer,
2543 for (i = 0; i < lvl_table_len && i <
ARRAY_SIZE(buffer); i++) {
2545 dprintk(
"Brightness level: %d\n", buffer[i]);
2550 if (buffer[i] >
max)
2552 if (buffer[i] < min)
2557 dprintk(
"Brightness levels: min=%d max=%d\n", props->
offset,
2561 static void sony_nc_backlight_setup(
void)
2564 int max_brightness = 0;
2568 if (sony_find_snc_handle(0x12f) >= 0) {
2569 ops = &sony_backlight_ng_ops;
2574 }
else if (sony_find_snc_handle(0x137) >= 0) {
2575 ops = &sony_backlight_ng_ops;
2580 }
else if (sony_find_snc_handle(0x143) >= 0) {
2581 ops = &sony_backlight_ng_ops;
2588 ops = &sony_backlight_ops;
2602 pr_warn(
"unable to register backlight device\n");
2609 static void sony_nc_backlight_cleanup(
void)
2615 static int sony_nc_add(
struct acpi_device *device)
2624 sony_nc_acpi_device = device;
2625 strcpy(acpi_device_class(device),
"sony/hotkey");
2627 sony_nc_acpi_handle = device->handle;
2632 if (!result && !device->status.present) {
2633 dprintk(
"Device not present\n");
2638 result = sony_pf_add();
2644 sony_nc_acpi_handle, 1, sony_walk_callback,
2647 pr_warn(
"unable to walk acpi resources\n");
2653 result = sony_laptop_setup_input(device);
2655 pr_err(
"Unable to create input devices\n");
2662 if (sony_nc_int_call(sony_nc_acpi_handle,
"ECON", &arg,
NULL))
2663 dprintk(
"ECON Method failed\n");
2670 result = sony_nc_handles_setup(sony_pf_device);
2672 sony_nc_function_setup(device, sony_pf_device);
2677 pr_info(
"brightness ignored, must be controlled by ACPI video driver\n");
2679 sony_nc_backlight_setup();
2683 for (item = sony_nc_values; item->
name; ++
item) {
2693 dprintk(
"Found %s getter: %s\n",
2705 dprintk(
"Found %s setter: %s\n",
2712 if (item->
devattr.attr.mode != 0) {
2724 for (item = sony_nc_values; item->
name; ++
item) {
2727 sony_nc_backlight_cleanup();
2728 sony_nc_function_cleanup(sony_pf_device);
2729 sony_nc_handles_cleanup(sony_pf_device);
2732 sony_laptop_remove_input();
2738 sony_nc_rfkill_cleanup();
2742 static int sony_nc_remove(
struct acpi_device *device,
int type)
2746 sony_nc_backlight_cleanup();
2748 sony_nc_acpi_device =
NULL;
2750 for (item = sony_nc_values; item->
name; ++
item) {
2754 sony_nc_function_cleanup(sony_pf_device);
2755 sony_nc_handles_cleanup(sony_pf_device);
2757 sony_laptop_remove_input();
2775 static struct acpi_driver sony_nc_driver = {
2778 .ids = sony_nc_device_ids,
2782 .remove = sony_nc_remove,
2783 .notify = sony_nc_notify,
2785 .drv.pm = &sony_nc_pm,
2790 #define SONYPI_DEVICE_TYPE1 0x00000001
2791 #define SONYPI_DEVICE_TYPE2 0x00000002
2792 #define SONYPI_DEVICE_TYPE3 0x00000004
2794 #define SONYPI_TYPE1_OFFSET 0x04
2795 #define SONYPI_TYPE2_OFFSET 0x12
2796 #define SONYPI_TYPE3_OFFSET 0x12
2809 struct sonypi_eventtypes {
2836 static int spic_drv_registered;
2839 #define SONYPI_JOGGER_MASK 0x00000001
2840 #define SONYPI_CAPTURE_MASK 0x00000002
2841 #define SONYPI_FNKEY_MASK 0x00000004
2842 #define SONYPI_BLUETOOTH_MASK 0x00000008
2843 #define SONYPI_PKEY_MASK 0x00000010
2844 #define SONYPI_BACK_MASK 0x00000020
2845 #define SONYPI_HELP_MASK 0x00000040
2846 #define SONYPI_LID_MASK 0x00000080
2847 #define SONYPI_ZOOM_MASK 0x00000100
2848 #define SONYPI_THUMBPHRASE_MASK 0x00000200
2849 #define SONYPI_MEYE_MASK 0x00000400
2850 #define SONYPI_MEMORYSTICK_MASK 0x00000800
2851 #define SONYPI_BATTERY_MASK 0x00001000
2852 #define SONYPI_WIRELESS_MASK 0x00002000
3012 static struct sonypi_eventtypes type1_events[] = {
3013 { 0, 0xffffffff, sonypi_releaseev },
3025 static struct sonypi_eventtypes type2_events[] = {
3026 { 0, 0xffffffff, sonypi_releaseev },
3042 static struct sonypi_eventtypes type3_events[] = {
3043 { 0, 0xffffffff, sonypi_releaseev },
3058 #define ITERATIONS_LONG 10000
3059 #define ITERATIONS_SHORT 10
3060 #define wait_on_command(command, iterations) { \
3061 unsigned int n = iterations; \
3062 while (--n && (command)) \
3065 dprintk("command failed at %s : %s (line %d)\n", \
3066 __FILE__, __func__, __LINE__); \
3069 static u8 sony_pic_call1(
u8 dev)
3078 dprintk(
"sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1);
3082 static u8 sony_pic_call2(
u8 dev,
u8 fn)
3093 dprintk(
"sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1);
3097 static u8 sony_pic_call3(
u8 dev,
u8 fn,
u8 v)
3108 dprintk(
"sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
3116 static int type3_handle_irq(
const u8 data_mask,
const u8 ev)
3125 if (data_mask == 0x31) {
3126 if (ev == 0x5c || ev == 0x5f)
3127 sony_pic_call1(0xA0);
3128 else if (ev == 0x61)
3129 sony_pic_call1(0xB3);
3135 static void sony_pic_detect_device_type(
struct sony_pic_dev *dev)
3196 pr_info(
"detected Type%d model\n",
3202 #define SONYPI_CAMERA_PICTURE 5
3203 #define SONYPI_CAMERA_CONTROL 0x10
3205 #define SONYPI_CAMERA_BRIGHTNESS 0
3206 #define SONYPI_CAMERA_CONTRAST 1
3207 #define SONYPI_CAMERA_HUE 2
3208 #define SONYPI_CAMERA_COLOR 3
3209 #define SONYPI_CAMERA_SHARPNESS 4
3211 #define SONYPI_CAMERA_EXPOSURE_MASK 0xC
3212 #define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
3213 #define SONYPI_CAMERA_PICTURE_MODE_MASK 0x30
3214 #define SONYPI_CAMERA_MUTE_MASK 0x40
3217 #define SONYPI_CAMERA_AGC 6
3218 #define SONYPI_CAMERA_AGC_MASK 0x30
3219 #define SONYPI_CAMERA_SHUTTER_MASK 0x7
3221 #define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
3222 #define SONYPI_CAMERA_CONTROL 0x10
3224 #define SONYPI_CAMERA_STATUS 7
3225 #define SONYPI_CAMERA_STATUS_READY 0x2
3226 #define SONYPI_CAMERA_STATUS_POSITION 0x4
3228 #define SONYPI_DIRECTION_BACKWARDS 0x4
3230 #define SONYPI_CAMERA_REVISION 8
3231 #define SONYPI_CAMERA_ROMVERSION 9
3233 static int __sony_pic_camera_ready(
void)
3241 static int __sony_pic_camera_off(
void)
3244 pr_warn(
"camera control not enabled\n");
3253 sony_pic_call2(0x91, 0);
3259 static int __sony_pic_camera_on(
void)
3264 pr_warn(
"camera control not enabled\n");
3271 for (j = 5; j > 0; j--) {
3273 for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
3275 sony_pic_call1(0x93);
3277 for (i = 400; i > 0; i--) {
3278 if (__sony_pic_camera_ready())
3287 pr_warn(
"failed to power on camera\n");
3308 case SONY_PIC_COMMAND_SETCAMERA:
3310 __sony_pic_camera_on();
3312 __sony_pic_camera_off();
3314 case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
3318 case SONY_PIC_COMMAND_SETCAMERACONTRAST:
3322 case SONY_PIC_COMMAND_SETCAMERAHUE:
3326 case SONY_PIC_COMMAND_SETCAMERACOLOR:
3330 case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
3334 case SONY_PIC_COMMAND_SETCAMERAPICTURE:
3338 case SONY_PIC_COMMAND_SETCAMERAAGC:
3343 pr_err(
"sony_pic_camera_command invalid: %d\n", command);
3352 static void __sony_pic_set_wwanpower(
u8 state)
3357 sony_pic_call2(0xB0, state);
3358 sony_pic_call1(0x82);
3362 static ssize_t sony_pic_wwanpower_store(
struct device *dev,
3364 const char *buffer,
size_t count)
3366 unsigned long value;
3370 if (kstrtoul(buffer, 10, &value))
3374 __sony_pic_set_wwanpower(value);
3380 static ssize_t sony_pic_wwanpower_show(
struct device *dev,
3391 static void __sony_pic_set_bluetoothpower(
u8 state)
3396 sony_pic_call2(0x96, state);
3397 sony_pic_call1(0x82);
3401 static ssize_t sony_pic_bluetoothpower_store(
struct device *dev,
3403 const char *buffer,
size_t count)
3405 unsigned long value;
3409 if (kstrtoul(buffer, 10, &value))
3413 __sony_pic_set_bluetoothpower(value);
3419 static ssize_t sony_pic_bluetoothpower_show(
struct device *dev,
3431 #define SONY_PIC_FAN0_STATUS 0x93
3432 static int sony_pic_set_fanspeed(
unsigned long value)
3437 static int sony_pic_get_fanspeed(
u8 *value)
3442 static ssize_t sony_pic_fanspeed_store(
struct device *dev,
3444 const char *buffer,
size_t count)
3446 unsigned long value;
3450 if (kstrtoul(buffer, 10, &value))
3453 if (sony_pic_set_fanspeed(value))
3459 static ssize_t sony_pic_fanspeed_show(
struct device *dev,
3463 if (sony_pic_get_fanspeed(&value))
3469 #define SPIC_ATTR(_name, _mode) \
3470 struct device_attribute spic_attr_##_name = __ATTR(_name, \
3471 _mode, sony_pic_## _name ##_show, \
3472 sony_pic_## _name ##_store)
3478 static struct attribute *spic_attributes[] = {
3479 &spic_attr_bluetoothpower.attr,
3480 &spic_attr_wwanpower.attr,
3481 &spic_attr_fanspeed.attr,
3486 .attrs = spic_attributes
3490 #ifdef CONFIG_SONYPI_COMPAT
3493 #define SONYPI_BAT_FLAGS 0x81
3494 #define SONYPI_LCD_LIGHT 0x96
3495 #define SONYPI_BAT1_PCTRM 0xa0
3496 #define SONYPI_BAT1_LEFT 0xa2
3497 #define SONYPI_BAT1_MAXRT 0xa4
3498 #define SONYPI_BAT2_PCTRM 0xa8
3499 #define SONYPI_BAT2_LEFT 0xaa
3500 #define SONYPI_BAT2_MAXRT 0xac
3501 #define SONYPI_BAT1_MAXTK 0xb0
3502 #define SONYPI_BAT1_FULL 0xb2
3503 #define SONYPI_BAT2_MAXTK 0xb8
3504 #define SONYPI_BAT2_FULL 0xba
3505 #define SONYPI_TEMP_STATUS 0xC1
3507 struct sonypi_compat_s {
3514 static struct sonypi_compat_s sonypi_compat = {
3518 static int sonypi_misc_fasync(
int fd,
struct file *filp,
int on)
3520 return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
3532 unsigned long flags;
3539 spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
3544 static ssize_t sonypi_misc_read(
struct file *file,
char __user *
buf,
3545 size_t count, loff_t *pos)
3550 if ((
kfifo_len(&sonypi_compat.fifo) == 0) &&
3559 while (ret < count &&
3561 &sonypi_compat.fifo_lock) ==
sizeof(c))) {
3568 struct inode *inode = file->
f_path.dentry->d_inode;
3575 static unsigned int sonypi_misc_poll(
struct file *file,
poll_table *
wait)
3577 poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
3583 static int ec_read16(
u8 addr,
u16 *value)
3588 if (
ec_read(addr + 1, &val_hb))
3590 *value = val_lb | (val_hb << 8);
3594 static long sonypi_misc_ioctl(
struct file *
fp,
unsigned int cmd,
3610 if (sony_nc_int_call(sony_nc_acpi_handle,
"GBRT",
NULL,
3615 val8 = ((value & 0xff) - 1) << 5;
3628 value = (val8 >> 5) + 1;
3629 if (sony_nc_int_call(sony_nc_acpi_handle,
"SBRT", &value,
3689 __sony_pic_set_bluetoothpower(val8);
3693 if (sony_pic_get_fanspeed(&val8)) {
3705 if (sony_pic_set_fanspeed(val8))
3726 .read = sonypi_misc_read,
3727 .poll = sonypi_misc_poll,
3728 .open = sonypi_misc_open,
3729 .release = sonypi_misc_release,
3730 .fasync = sonypi_misc_fasync,
3731 .unlocked_ioctl = sonypi_misc_ioctl,
3735 static struct miscdevice sonypi_misc_device = {
3738 .fops = &sonypi_misc_fops,
3741 static void sonypi_compat_report_event(
u8 event)
3744 sizeof(event), &sonypi_compat.fifo_lock);
3749 static int sonypi_compat_init(
void)
3757 pr_err(
"kfifo_alloc failed\n");
3767 pr_err(
"misc_register failed\n");
3768 goto err_free_kfifo;
3771 pr_info(
"device allocated minor is %d\n",
3772 sonypi_misc_device.
minor);
3781 static void sonypi_compat_exit(
void)
3787 static int sonypi_compat_init(
void) {
return 0; }
3788 static void sonypi_compat_exit(
void) { }
3789 static void sonypi_compat_report_event(
u8 event) { }
3801 switch (resource->
type) {
3826 dprintk(
"Blank IRQ resource\n");
3835 interrupt = kzalloc(
sizeof(*interrupt),
3844 interrupt->
irq.interrupt_count = 1;
3855 dprintk(
"Blank IO resource\n");
3859 if (!ioport->
io1.minimum) {
3861 dprintk(
"IO1 at 0x%.4x (0x%.2x)\n", ioport->
io1.minimum,
3862 ioport->
io1.address_length);
3864 else if (!ioport->
io2.minimum) {
3866 dprintk(
"IO2 at 0x%.4x (0x%.2x)\n", ioport->
io2.minimum,
3867 ioport->
io2.address_length);
3870 pr_err(
"Unknown SPIC Type, more than 2 IO Ports\n");
3876 dprintk(
"Resource %d isn't an IRQ nor an IO port\n",
3885 static int sony_pic_possible_resources(
struct acpi_device *device)
3898 pr_warn(
"Unable to read status\n");
3902 if (!device->status.enabled)
3912 sony_pic_read_possible_resource, &spic_dev);
3924 static int sony_pic_disable(
struct acpi_device *device)
3942 static int sony_pic_enable(
struct acpi_device *device,
3966 if (!ioport || !irq)
3970 resource = kzalloc(
sizeof(*resource) + 1,
GFP_KERNEL);
3974 buffer.
length =
sizeof(*resource) + 1;
4027 pr_err(
"Error evaluating _SRS\n");
4033 sony_pic_call1(0x82);
4034 sony_pic_call2(0x81, 0xff);
4035 sony_pic_call1(compat ? 0x92 : 0x82);
4052 u8 device_event = 0;
4063 dprintk(
"event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4067 if (ev == 0x00 || ev == 0xff)
4096 dprintk(
"unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
4102 sony_laptop_report_input_event(device_event);
4103 acpi_bus_generate_proc_event(dev->
acpi_dev, 1, device_event);
4104 sonypi_compat_report_event(device_event);
4113 static int sony_pic_remove(
struct acpi_device *device,
int type)
4118 if (sony_pic_disable(device)) {
4119 pr_err(
"Couldn't disable device\n");
4130 sonypi_compat_exit();
4132 sony_laptop_remove_input();
4153 static int sony_pic_add(
struct acpi_device *device)
4162 strcpy(acpi_device_class(device),
"sony/hotkey");
4163 sony_pic_detect_device_type(&spic_dev);
4167 result = sony_pic_possible_resources(device);
4169 pr_err(
"Unable to read possible resources\n");
4170 goto err_free_resources;
4174 result = sony_laptop_setup_input(device);
4176 pr_err(
"Unable to create input devices\n");
4177 goto err_free_resources;
4180 if (sonypi_compat_init())
4181 goto err_remove_input;
4186 "Sony Programmable I/O Device")) {
4187 dprintk(
"I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
4188 io->
io1.minimum, io->
io1.maximum,
4189 io->
io1.address_length);
4191 if (io->
io2.minimum) {
4193 io->
io2.address_length,
4194 "Sony Programmable I/O Device")) {
4195 dprintk(
"I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
4196 io->
io2.minimum, io->
io2.maximum,
4197 io->
io2.address_length);
4202 dprintk(
"Unable to get I/O port2: "
4203 "0x%.4x (0x%.4x) + 0x%.2x\n",
4204 io->
io2.minimum, io->
io2.maximum,
4205 io->
io2.address_length);
4207 io->
io1.address_length);
4217 pr_err(
"Failed to request_region\n");
4219 goto err_remove_compat;
4225 0,
"sony-laptop", &spic_dev)) {
4226 dprintk(
"IRQ: %d - triggering: %d - "
4227 "polarity: %d - shr: %d\n",
4228 irq->
irq.interrupts[0],
4229 irq->
irq.triggering,
4237 pr_err(
"Failed to request_irq\n");
4239 goto err_release_region;
4245 pr_err(
"Couldn't enable device\n");
4251 result = sony_pf_add();
4253 goto err_disable_device;
4265 sony_pic_disable(device);
4278 sonypi_compat_exit();
4281 sony_laptop_remove_input();
4298 #ifdef CONFIG_PM_SLEEP
4299 static int sony_pic_suspend(
struct device *dev)
4301 if (sony_pic_disable(to_acpi_device(dev)))
4306 static int sony_pic_resume(
struct device *dev)
4308 sony_pic_enable(to_acpi_device(dev),
4321 static struct acpi_driver sony_pic_driver = {
4324 .ids = sony_pic_device_ids,
4327 .add = sony_pic_add,
4328 .remove = sony_pic_remove,
4330 .drv.pm = &sony_pic_pm,
4335 .ident =
"Sony Vaio",
4342 .ident =
"Sony Vaio",
4351 static int __init sony_laptop_init(
void)
4358 pr_err(
"Unable to register SPIC driver\n");
4361 spic_drv_registered = 1;
4366 pr_err(
"Unable to register SNC driver\n");
4367 goto out_unregister_pic;
4373 if (spic_drv_registered)
4379 static void __exit sony_laptop_exit(
void)
4382 if (spic_drv_registered)