diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/platform/x86/sony-laptop.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 239 |
1 files changed, 149 insertions, 90 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index a2a742c8ff7e..1387c5f9c24d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/kfifo.h> | 58 | #include <linux/kfifo.h> |
59 | #include <linux/workqueue.h> | 59 | #include <linux/workqueue.h> |
60 | #include <linux/acpi.h> | 60 | #include <linux/acpi.h> |
61 | #include <linux/slab.h> | ||
61 | #include <acpi/acpi_drivers.h> | 62 | #include <acpi/acpi_drivers.h> |
62 | #include <acpi/acpi_bus.h> | 63 | #include <acpi/acpi_bus.h> |
63 | #include <asm/uaccess.h> | 64 | #include <asm/uaccess.h> |
@@ -131,6 +132,7 @@ enum sony_nc_rfkill { | |||
131 | N_SONY_RFKILL, | 132 | N_SONY_RFKILL, |
132 | }; | 133 | }; |
133 | 134 | ||
135 | static int sony_rfkill_handle; | ||
134 | static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; | 136 | static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; |
135 | static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; | 137 | static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; |
136 | static void sony_nc_rfkill_update(void); | 138 | static void sony_nc_rfkill_update(void); |
@@ -142,9 +144,9 @@ struct sony_laptop_input_s { | |||
142 | atomic_t users; | 144 | atomic_t users; |
143 | struct input_dev *jog_dev; | 145 | struct input_dev *jog_dev; |
144 | struct input_dev *key_dev; | 146 | struct input_dev *key_dev; |
145 | struct kfifo *fifo; | 147 | struct kfifo fifo; |
146 | spinlock_t fifo_lock; | 148 | spinlock_t fifo_lock; |
147 | struct workqueue_struct *wq; | 149 | struct timer_list release_key_timer; |
148 | }; | 150 | }; |
149 | 151 | ||
150 | static struct sony_laptop_input_s sony_laptop_input = { | 152 | static struct sony_laptop_input_s sony_laptop_input = { |
@@ -232,6 +234,7 @@ static int sony_laptop_input_index[] = { | |||
232 | 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ | 234 | 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ |
233 | 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | 235 | 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ |
234 | -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ | 236 | -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ |
237 | 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ | ||
235 | }; | 238 | }; |
236 | 239 | ||
237 | static int sony_laptop_input_keycode_map[] = { | 240 | static int sony_laptop_input_keycode_map[] = { |
@@ -293,22 +296,30 @@ static int sony_laptop_input_keycode_map[] = { | |||
293 | KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ | 296 | KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ |
294 | KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ | 297 | KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ |
295 | KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | 298 | KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ |
299 | KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ | ||
296 | }; | 300 | }; |
297 | 301 | ||
298 | /* release buttons after a short delay if pressed */ | 302 | /* release buttons after a short delay if pressed */ |
299 | static void do_sony_laptop_release_key(struct work_struct *work) | 303 | static void do_sony_laptop_release_key(unsigned long unused) |
300 | { | 304 | { |
301 | struct sony_laptop_keypress kp; | 305 | struct sony_laptop_keypress kp; |
306 | unsigned long flags; | ||
307 | |||
308 | spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags); | ||
302 | 309 | ||
303 | while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, | 310 | if (kfifo_out(&sony_laptop_input.fifo, |
304 | sizeof(kp)) == sizeof(kp)) { | 311 | (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { |
305 | msleep(10); | ||
306 | input_report_key(kp.dev, kp.key, 0); | 312 | input_report_key(kp.dev, kp.key, 0); |
307 | input_sync(kp.dev); | 313 | input_sync(kp.dev); |
308 | } | 314 | } |
315 | |||
316 | /* If there is something in the fifo schedule next release. */ | ||
317 | if (kfifo_len(&sony_laptop_input.fifo) != 0) | ||
318 | mod_timer(&sony_laptop_input.release_key_timer, | ||
319 | jiffies + msecs_to_jiffies(10)); | ||
320 | |||
321 | spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); | ||
309 | } | 322 | } |
310 | static DECLARE_WORK(sony_laptop_release_key_work, | ||
311 | do_sony_laptop_release_key); | ||
312 | 323 | ||
313 | /* forward event to the input subsystem */ | 324 | /* forward event to the input subsystem */ |
314 | static void sony_laptop_report_input_event(u8 event) | 325 | static void sony_laptop_report_input_event(u8 event) |
@@ -362,12 +373,13 @@ static void sony_laptop_report_input_event(u8 event) | |||
362 | /* we emit the scancode so we can always remap the key */ | 373 | /* we emit the scancode so we can always remap the key */ |
363 | input_event(kp.dev, EV_MSC, MSC_SCAN, event); | 374 | input_event(kp.dev, EV_MSC, MSC_SCAN, event); |
364 | input_sync(kp.dev); | 375 | input_sync(kp.dev); |
365 | kfifo_put(sony_laptop_input.fifo, | ||
366 | (unsigned char *)&kp, sizeof(kp)); | ||
367 | 376 | ||
368 | if (!work_pending(&sony_laptop_release_key_work)) | 377 | /* schedule key release */ |
369 | queue_work(sony_laptop_input.wq, | 378 | kfifo_in_locked(&sony_laptop_input.fifo, |
370 | &sony_laptop_release_key_work); | 379 | (unsigned char *)&kp, sizeof(kp), |
380 | &sony_laptop_input.fifo_lock); | ||
381 | mod_timer(&sony_laptop_input.release_key_timer, | ||
382 | jiffies + msecs_to_jiffies(10)); | ||
371 | } else | 383 | } else |
372 | dprintk("unknown input event %.2x\n", event); | 384 | dprintk("unknown input event %.2x\n", event); |
373 | } | 385 | } |
@@ -385,29 +397,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) | |||
385 | 397 | ||
386 | /* kfifo */ | 398 | /* kfifo */ |
387 | spin_lock_init(&sony_laptop_input.fifo_lock); | 399 | spin_lock_init(&sony_laptop_input.fifo_lock); |
388 | sony_laptop_input.fifo = | 400 | error = kfifo_alloc(&sony_laptop_input.fifo, |
389 | kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, | 401 | SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); |
390 | &sony_laptop_input.fifo_lock); | 402 | if (error) { |
391 | if (IS_ERR(sony_laptop_input.fifo)) { | ||
392 | printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); | 403 | printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); |
393 | error = PTR_ERR(sony_laptop_input.fifo); | ||
394 | goto err_dec_users; | 404 | goto err_dec_users; |
395 | } | 405 | } |
396 | 406 | ||
397 | /* init workqueue */ | 407 | setup_timer(&sony_laptop_input.release_key_timer, |
398 | sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); | 408 | do_sony_laptop_release_key, 0); |
399 | if (!sony_laptop_input.wq) { | ||
400 | printk(KERN_ERR DRV_PFX | ||
401 | "Unable to create workqueue.\n"); | ||
402 | error = -ENXIO; | ||
403 | goto err_free_kfifo; | ||
404 | } | ||
405 | 409 | ||
406 | /* input keys */ | 410 | /* input keys */ |
407 | key_dev = input_allocate_device(); | 411 | key_dev = input_allocate_device(); |
408 | if (!key_dev) { | 412 | if (!key_dev) { |
409 | error = -ENOMEM; | 413 | error = -ENOMEM; |
410 | goto err_destroy_wq; | 414 | goto err_free_kfifo; |
411 | } | 415 | } |
412 | 416 | ||
413 | key_dev->name = "Sony Vaio Keys"; | 417 | key_dev->name = "Sony Vaio Keys"; |
@@ -416,18 +420,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) | |||
416 | key_dev->dev.parent = &acpi_device->dev; | 420 | key_dev->dev.parent = &acpi_device->dev; |
417 | 421 | ||
418 | /* Initialize the Input Drivers: special keys */ | 422 | /* Initialize the Input Drivers: special keys */ |
419 | set_bit(EV_KEY, key_dev->evbit); | 423 | input_set_capability(key_dev, EV_MSC, MSC_SCAN); |
420 | set_bit(EV_MSC, key_dev->evbit); | 424 | |
421 | set_bit(MSC_SCAN, key_dev->mscbit); | 425 | __set_bit(EV_KEY, key_dev->evbit); |
422 | key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); | 426 | key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); |
423 | key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); | 427 | key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); |
424 | key_dev->keycode = &sony_laptop_input_keycode_map; | 428 | key_dev->keycode = &sony_laptop_input_keycode_map; |
425 | for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { | 429 | for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) |
426 | if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { | 430 | __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit); |
427 | set_bit(sony_laptop_input_keycode_map[i], | 431 | __clear_bit(KEY_RESERVED, key_dev->keybit); |
428 | key_dev->keybit); | ||
429 | } | ||
430 | } | ||
431 | 432 | ||
432 | error = input_register_device(key_dev); | 433 | error = input_register_device(key_dev); |
433 | if (error) | 434 | if (error) |
@@ -447,9 +448,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) | |||
447 | jog_dev->id.vendor = PCI_VENDOR_ID_SONY; | 448 | jog_dev->id.vendor = PCI_VENDOR_ID_SONY; |
448 | key_dev->dev.parent = &acpi_device->dev; | 449 | key_dev->dev.parent = &acpi_device->dev; |
449 | 450 | ||
450 | jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 451 | input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE); |
451 | jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); | 452 | input_set_capability(jog_dev, EV_REL, REL_WHEEL); |
452 | jog_dev->relbit[0] = BIT_MASK(REL_WHEEL); | ||
453 | 453 | ||
454 | error = input_register_device(jog_dev); | 454 | error = input_register_device(jog_dev); |
455 | if (error) | 455 | if (error) |
@@ -470,11 +470,8 @@ err_unregister_keydev: | |||
470 | err_free_keydev: | 470 | err_free_keydev: |
471 | input_free_device(key_dev); | 471 | input_free_device(key_dev); |
472 | 472 | ||
473 | err_destroy_wq: | ||
474 | destroy_workqueue(sony_laptop_input.wq); | ||
475 | |||
476 | err_free_kfifo: | 473 | err_free_kfifo: |
477 | kfifo_free(sony_laptop_input.fifo); | 474 | kfifo_free(&sony_laptop_input.fifo); |
478 | 475 | ||
479 | err_dec_users: | 476 | err_dec_users: |
480 | atomic_dec(&sony_laptop_input.users); | 477 | atomic_dec(&sony_laptop_input.users); |
@@ -483,12 +480,23 @@ err_dec_users: | |||
483 | 480 | ||
484 | static void sony_laptop_remove_input(void) | 481 | static void sony_laptop_remove_input(void) |
485 | { | 482 | { |
486 | /* cleanup only after the last user has gone */ | 483 | struct sony_laptop_keypress kp = { NULL }; |
484 | |||
485 | /* Cleanup only after the last user has gone */ | ||
487 | if (!atomic_dec_and_test(&sony_laptop_input.users)) | 486 | if (!atomic_dec_and_test(&sony_laptop_input.users)) |
488 | return; | 487 | return; |
489 | 488 | ||
490 | /* flush workqueue first */ | 489 | del_timer_sync(&sony_laptop_input.release_key_timer); |
491 | flush_workqueue(sony_laptop_input.wq); | 490 | |
491 | /* | ||
492 | * Generate key-up events for remaining keys. Note that we don't | ||
493 | * need locking since nobody is adding new events to the kfifo. | ||
494 | */ | ||
495 | while (kfifo_out(&sony_laptop_input.fifo, | ||
496 | (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { | ||
497 | input_report_key(kp.dev, kp.key, 0); | ||
498 | input_sync(kp.dev); | ||
499 | } | ||
492 | 500 | ||
493 | /* destroy input devs */ | 501 | /* destroy input devs */ |
494 | input_unregister_device(sony_laptop_input.key_dev); | 502 | input_unregister_device(sony_laptop_input.key_dev); |
@@ -499,8 +507,7 @@ static void sony_laptop_remove_input(void) | |||
499 | sony_laptop_input.jog_dev = NULL; | 507 | sony_laptop_input.jog_dev = NULL; |
500 | } | 508 | } |
501 | 509 | ||
502 | destroy_workqueue(sony_laptop_input.wq); | 510 | kfifo_free(&sony_laptop_input.fifo); |
503 | kfifo_free(sony_laptop_input.fifo); | ||
504 | } | 511 | } |
505 | 512 | ||
506 | /*********** Platform Device ***********/ | 513 | /*********** Platform Device ***********/ |
@@ -890,6 +897,8 @@ static struct sony_nc_event sony_100_events[] = { | |||
890 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | 897 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, |
891 | { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, | 898 | { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, |
892 | { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, | 899 | { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
900 | { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, | ||
901 | { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, | ||
893 | { 0, 0 }, | 902 | { 0, 0 }, |
894 | }; | 903 | }; |
895 | 904 | ||
@@ -961,7 +970,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) | |||
961 | else | 970 | else |
962 | sony_laptop_report_input_event(ev); | 971 | sony_laptop_report_input_event(ev); |
963 | } | 972 | } |
964 | } else if (sony_find_snc_handle(0x124) == ev) { | 973 | } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { |
965 | sony_nc_rfkill_update(); | 974 | sony_nc_rfkill_update(); |
966 | return; | 975 | return; |
967 | } | 976 | } |
@@ -1067,7 +1076,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) | |||
1067 | if (!blocked) | 1076 | if (!blocked) |
1068 | argument |= 0xff0000; | 1077 | argument |= 0xff0000; |
1069 | 1078 | ||
1070 | return sony_call_snc_handle(0x124, argument, &result); | 1079 | return sony_call_snc_handle(sony_rfkill_handle, argument, &result); |
1071 | } | 1080 | } |
1072 | 1081 | ||
1073 | static const struct rfkill_ops sony_rfkill_ops = { | 1082 | static const struct rfkill_ops sony_rfkill_ops = { |
@@ -1110,7 +1119,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, | |||
1110 | if (!rfk) | 1119 | if (!rfk) |
1111 | return -ENOMEM; | 1120 | return -ENOMEM; |
1112 | 1121 | ||
1113 | sony_call_snc_handle(0x124, 0x200, &result); | 1122 | sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); |
1114 | hwblock = !(result & 0x1); | 1123 | hwblock = !(result & 0x1); |
1115 | rfkill_set_hw_state(rfk, hwblock); | 1124 | rfkill_set_hw_state(rfk, hwblock); |
1116 | 1125 | ||
@@ -1129,7 +1138,7 @@ static void sony_nc_rfkill_update() | |||
1129 | int result; | 1138 | int result; |
1130 | bool hwblock; | 1139 | bool hwblock; |
1131 | 1140 | ||
1132 | sony_call_snc_handle(0x124, 0x200, &result); | 1141 | sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); |
1133 | hwblock = !(result & 0x1); | 1142 | hwblock = !(result & 0x1); |
1134 | 1143 | ||
1135 | for (i = 0; i < N_SONY_RFKILL; i++) { | 1144 | for (i = 0; i < N_SONY_RFKILL; i++) { |
@@ -1145,36 +1154,82 @@ static void sony_nc_rfkill_update() | |||
1145 | continue; | 1154 | continue; |
1146 | } | 1155 | } |
1147 | 1156 | ||
1148 | sony_call_snc_handle(0x124, argument, &result); | 1157 | sony_call_snc_handle(sony_rfkill_handle, argument, &result); |
1149 | rfkill_set_states(sony_rfkill_devices[i], | 1158 | rfkill_set_states(sony_rfkill_devices[i], |
1150 | !(result & 0xf), false); | 1159 | !(result & 0xf), false); |
1151 | } | 1160 | } |
1152 | } | 1161 | } |
1153 | 1162 | ||
1154 | static int sony_nc_rfkill_setup(struct acpi_device *device) | 1163 | static void sony_nc_rfkill_setup(struct acpi_device *device) |
1155 | { | 1164 | { |
1156 | int result, ret; | 1165 | int offset; |
1166 | u8 dev_code, i; | ||
1167 | acpi_status status; | ||
1168 | struct acpi_object_list params; | ||
1169 | union acpi_object in_obj; | ||
1170 | union acpi_object *device_enum; | ||
1171 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1157 | 1172 | ||
1158 | if (sony_find_snc_handle(0x124) == -1) | 1173 | offset = sony_find_snc_handle(0x124); |
1159 | return -1; | 1174 | if (offset == -1) { |
1175 | offset = sony_find_snc_handle(0x135); | ||
1176 | if (offset == -1) | ||
1177 | return; | ||
1178 | else | ||
1179 | sony_rfkill_handle = 0x135; | ||
1180 | } else | ||
1181 | sony_rfkill_handle = 0x124; | ||
1182 | dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); | ||
1160 | 1183 | ||
1161 | ret = sony_call_snc_handle(0x124, 0xb00, &result); | 1184 | /* need to read the whole buffer returned by the acpi call to SN06 |
1162 | if (ret) { | 1185 | * here otherwise we may miss some features |
1163 | printk(KERN_INFO DRV_PFX | 1186 | */ |
1164 | "Unable to enumerate rfkill devices: %x\n", ret); | 1187 | params.count = 1; |
1165 | return ret; | 1188 | params.pointer = &in_obj; |
1189 | in_obj.type = ACPI_TYPE_INTEGER; | ||
1190 | in_obj.integer.value = offset; | ||
1191 | status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, | ||
1192 | &buffer); | ||
1193 | if (ACPI_FAILURE(status)) { | ||
1194 | dprintk("Radio device enumeration failed\n"); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1198 | device_enum = (union acpi_object *) buffer.pointer; | ||
1199 | if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { | ||
1200 | printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", | ||
1201 | device_enum->type); | ||
1202 | goto out_no_enum; | ||
1166 | } | 1203 | } |
1167 | 1204 | ||
1168 | if (result & 0x1) | 1205 | /* the buffer is filled with magic numbers describing the devices |
1169 | sony_nc_setup_rfkill(device, SONY_WIFI); | 1206 | * available, 0xff terminates the enumeration |
1170 | if (result & 0x2) | 1207 | */ |
1171 | sony_nc_setup_rfkill(device, SONY_BLUETOOTH); | 1208 | for (i = 0; i < device_enum->buffer.length; i++) { |
1172 | if (result & 0x1c) | ||
1173 | sony_nc_setup_rfkill(device, SONY_WWAN); | ||
1174 | if (result & 0x20) | ||
1175 | sony_nc_setup_rfkill(device, SONY_WIMAX); | ||
1176 | 1209 | ||
1177 | return 0; | 1210 | dev_code = *(device_enum->buffer.pointer + i); |
1211 | if (dev_code == 0xff) | ||
1212 | break; | ||
1213 | |||
1214 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); | ||
1215 | |||
1216 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) | ||
1217 | sony_nc_setup_rfkill(device, SONY_WIFI); | ||
1218 | |||
1219 | if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) | ||
1220 | sony_nc_setup_rfkill(device, SONY_BLUETOOTH); | ||
1221 | |||
1222 | if ((0xf0 & dev_code) == 0x20 && | ||
1223 | !sony_rfkill_devices[SONY_WWAN]) | ||
1224 | sony_nc_setup_rfkill(device, SONY_WWAN); | ||
1225 | |||
1226 | if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) | ||
1227 | sony_nc_setup_rfkill(device, SONY_WIMAX); | ||
1228 | } | ||
1229 | |||
1230 | out_no_enum: | ||
1231 | kfree(buffer.pointer); | ||
1232 | return; | ||
1178 | } | 1233 | } |
1179 | 1234 | ||
1180 | static int sony_nc_add(struct acpi_device *device) | 1235 | static int sony_nc_add(struct acpi_device *device) |
@@ -1203,7 +1258,7 @@ static int sony_nc_add(struct acpi_device *device) | |||
1203 | 1258 | ||
1204 | if (debug) { | 1259 | if (debug) { |
1205 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, | 1260 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, |
1206 | 1, sony_walk_callback, NULL, NULL); | 1261 | 1, sony_walk_callback, NULL, NULL, NULL); |
1207 | if (ACPI_FAILURE(status)) { | 1262 | if (ACPI_FAILURE(status)) { |
1208 | printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); | 1263 | printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); |
1209 | result = -ENODEV; | 1264 | result = -ENODEV; |
@@ -1237,9 +1292,13 @@ static int sony_nc_add(struct acpi_device *device) | |||
1237 | "controlled by ACPI video driver\n"); | 1292 | "controlled by ACPI video driver\n"); |
1238 | } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", | 1293 | } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", |
1239 | &handle))) { | 1294 | &handle))) { |
1295 | struct backlight_properties props; | ||
1296 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
1297 | props.max_brightness = SONY_MAX_BRIGHTNESS - 1; | ||
1240 | sony_backlight_device = backlight_device_register("sony", NULL, | 1298 | sony_backlight_device = backlight_device_register("sony", NULL, |
1241 | NULL, | 1299 | NULL, |
1242 | &sony_backlight_ops); | 1300 | &sony_backlight_ops, |
1301 | &props); | ||
1243 | 1302 | ||
1244 | if (IS_ERR(sony_backlight_device)) { | 1303 | if (IS_ERR(sony_backlight_device)) { |
1245 | printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); | 1304 | printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); |
@@ -1248,8 +1307,6 @@ static int sony_nc_add(struct acpi_device *device) | |||
1248 | sony_backlight_device->props.brightness = | 1307 | sony_backlight_device->props.brightness = |
1249 | sony_backlight_get_brightness | 1308 | sony_backlight_get_brightness |
1250 | (sony_backlight_device); | 1309 | (sony_backlight_device); |
1251 | sony_backlight_device->props.max_brightness = | ||
1252 | SONY_MAX_BRIGHTNESS - 1; | ||
1253 | } | 1310 | } |
1254 | 1311 | ||
1255 | } | 1312 | } |
@@ -2079,7 +2136,7 @@ static struct attribute_group spic_attribute_group = { | |||
2079 | 2136 | ||
2080 | struct sonypi_compat_s { | 2137 | struct sonypi_compat_s { |
2081 | struct fasync_struct *fifo_async; | 2138 | struct fasync_struct *fifo_async; |
2082 | struct kfifo *fifo; | 2139 | struct kfifo fifo; |
2083 | spinlock_t fifo_lock; | 2140 | spinlock_t fifo_lock; |
2084 | wait_queue_head_t fifo_proc_list; | 2141 | wait_queue_head_t fifo_proc_list; |
2085 | atomic_t open_count; | 2142 | atomic_t open_count; |
@@ -2104,12 +2161,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) | |||
2104 | /* Flush input queue on first open */ | 2161 | /* Flush input queue on first open */ |
2105 | unsigned long flags; | 2162 | unsigned long flags; |
2106 | 2163 | ||
2107 | spin_lock_irqsave(sonypi_compat.fifo->lock, flags); | 2164 | spin_lock_irqsave(&sonypi_compat.fifo_lock, flags); |
2108 | 2165 | ||
2109 | if (atomic_inc_return(&sonypi_compat.open_count) == 1) | 2166 | if (atomic_inc_return(&sonypi_compat.open_count) == 1) |
2110 | __kfifo_reset(sonypi_compat.fifo); | 2167 | kfifo_reset(&sonypi_compat.fifo); |
2111 | 2168 | ||
2112 | spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); | 2169 | spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags); |
2113 | 2170 | ||
2114 | return 0; | 2171 | return 0; |
2115 | } | 2172 | } |
@@ -2120,17 +2177,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, | |||
2120 | ssize_t ret; | 2177 | ssize_t ret; |
2121 | unsigned char c; | 2178 | unsigned char c; |
2122 | 2179 | ||
2123 | if ((kfifo_len(sonypi_compat.fifo) == 0) && | 2180 | if ((kfifo_len(&sonypi_compat.fifo) == 0) && |
2124 | (file->f_flags & O_NONBLOCK)) | 2181 | (file->f_flags & O_NONBLOCK)) |
2125 | return -EAGAIN; | 2182 | return -EAGAIN; |
2126 | 2183 | ||
2127 | ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, | 2184 | ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, |
2128 | kfifo_len(sonypi_compat.fifo) != 0); | 2185 | kfifo_len(&sonypi_compat.fifo) != 0); |
2129 | if (ret) | 2186 | if (ret) |
2130 | return ret; | 2187 | return ret; |
2131 | 2188 | ||
2132 | while (ret < count && | 2189 | while (ret < count && |
2133 | (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { | 2190 | (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c), |
2191 | &sonypi_compat.fifo_lock) == sizeof(c))) { | ||
2134 | if (put_user(c, buf++)) | 2192 | if (put_user(c, buf++)) |
2135 | return -EFAULT; | 2193 | return -EFAULT; |
2136 | ret++; | 2194 | ret++; |
@@ -2147,7 +2205,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, | |||
2147 | static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) | 2205 | static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) |
2148 | { | 2206 | { |
2149 | poll_wait(file, &sonypi_compat.fifo_proc_list, wait); | 2207 | poll_wait(file, &sonypi_compat.fifo_proc_list, wait); |
2150 | if (kfifo_len(sonypi_compat.fifo)) | 2208 | if (kfifo_len(&sonypi_compat.fifo)) |
2151 | return POLLIN | POLLRDNORM; | 2209 | return POLLIN | POLLRDNORM; |
2152 | return 0; | 2210 | return 0; |
2153 | } | 2211 | } |
@@ -2309,7 +2367,8 @@ static struct miscdevice sonypi_misc_device = { | |||
2309 | 2367 | ||
2310 | static void sonypi_compat_report_event(u8 event) | 2368 | static void sonypi_compat_report_event(u8 event) |
2311 | { | 2369 | { |
2312 | kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); | 2370 | kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event, |
2371 | sizeof(event), &sonypi_compat.fifo_lock); | ||
2313 | kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); | 2372 | kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); |
2314 | wake_up_interruptible(&sonypi_compat.fifo_proc_list); | 2373 | wake_up_interruptible(&sonypi_compat.fifo_proc_list); |
2315 | } | 2374 | } |
@@ -2319,11 +2378,11 @@ static int sonypi_compat_init(void) | |||
2319 | int error; | 2378 | int error; |
2320 | 2379 | ||
2321 | spin_lock_init(&sonypi_compat.fifo_lock); | 2380 | spin_lock_init(&sonypi_compat.fifo_lock); |
2322 | sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, | 2381 | error = |
2323 | &sonypi_compat.fifo_lock); | 2382 | kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); |
2324 | if (IS_ERR(sonypi_compat.fifo)) { | 2383 | if (error) { |
2325 | printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); | 2384 | printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); |
2326 | return PTR_ERR(sonypi_compat.fifo); | 2385 | return error; |
2327 | } | 2386 | } |
2328 | 2387 | ||
2329 | init_waitqueue_head(&sonypi_compat.fifo_proc_list); | 2388 | init_waitqueue_head(&sonypi_compat.fifo_proc_list); |
@@ -2342,14 +2401,14 @@ static int sonypi_compat_init(void) | |||
2342 | return 0; | 2401 | return 0; |
2343 | 2402 | ||
2344 | err_free_kfifo: | 2403 | err_free_kfifo: |
2345 | kfifo_free(sonypi_compat.fifo); | 2404 | kfifo_free(&sonypi_compat.fifo); |
2346 | return error; | 2405 | return error; |
2347 | } | 2406 | } |
2348 | 2407 | ||
2349 | static void sonypi_compat_exit(void) | 2408 | static void sonypi_compat_exit(void) |
2350 | { | 2409 | { |
2351 | misc_deregister(&sonypi_misc_device); | 2410 | misc_deregister(&sonypi_misc_device); |
2352 | kfifo_free(sonypi_compat.fifo); | 2411 | kfifo_free(&sonypi_compat.fifo); |
2353 | } | 2412 | } |
2354 | #else | 2413 | #else |
2355 | static int sonypi_compat_init(void) { return 0; } | 2414 | static int sonypi_compat_init(void) { return 0; } |