aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c100
1 files changed, 53 insertions, 47 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 3f71a605a492..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>
@@ -145,7 +146,7 @@ struct sony_laptop_input_s {
145 struct input_dev *key_dev; 146 struct input_dev *key_dev;
146 struct kfifo fifo; 147 struct kfifo fifo;
147 spinlock_t fifo_lock; 148 spinlock_t fifo_lock;
148 struct workqueue_struct *wq; 149 struct timer_list release_key_timer;
149}; 150};
150 151
151static struct sony_laptop_input_s sony_laptop_input = { 152static struct sony_laptop_input_s sony_laptop_input = {
@@ -299,20 +300,26 @@ static int sony_laptop_input_keycode_map[] = {
299}; 300};
300 301
301/* release buttons after a short delay if pressed */ 302/* release buttons after a short delay if pressed */
302static void do_sony_laptop_release_key(struct work_struct *work) 303static void do_sony_laptop_release_key(unsigned long unused)
303{ 304{
304 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);
305 309
306 while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, 310 if (kfifo_out(&sony_laptop_input.fifo,
307 sizeof(kp), &sony_laptop_input.fifo_lock) 311 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
308 == sizeof(kp)) {
309 msleep(10);
310 input_report_key(kp.dev, kp.key, 0); 312 input_report_key(kp.dev, kp.key, 0);
311 input_sync(kp.dev); 313 input_sync(kp.dev);
312 } 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);
313} 322}
314static DECLARE_WORK(sony_laptop_release_key_work,
315 do_sony_laptop_release_key);
316 323
317/* forward event to the input subsystem */ 324/* forward event to the input subsystem */
318static void sony_laptop_report_input_event(u8 event) 325static void sony_laptop_report_input_event(u8 event)
@@ -366,13 +373,13 @@ static void sony_laptop_report_input_event(u8 event)
366 /* we emit the scancode so we can always remap the key */ 373 /* we emit the scancode so we can always remap the key */
367 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 374 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
368 input_sync(kp.dev); 375 input_sync(kp.dev);
369 kfifo_in_locked(&sony_laptop_input.fifo,
370 (unsigned char *)&kp, sizeof(kp),
371 &sony_laptop_input.fifo_lock);
372 376
373 if (!work_pending(&sony_laptop_release_key_work)) 377 /* schedule key release */
374 queue_work(sony_laptop_input.wq, 378 kfifo_in_locked(&sony_laptop_input.fifo,
375 &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));
376 } else 383 } else
377 dprintk("unknown input event %.2x\n", event); 384 dprintk("unknown input event %.2x\n", event);
378} 385}
@@ -390,27 +397,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
390 397
391 /* kfifo */ 398 /* kfifo */
392 spin_lock_init(&sony_laptop_input.fifo_lock); 399 spin_lock_init(&sony_laptop_input.fifo_lock);
393 error = 400 error = kfifo_alloc(&sony_laptop_input.fifo,
394 kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 401 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
395 if (error) { 402 if (error) {
396 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 403 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
397 goto err_dec_users; 404 goto err_dec_users;
398 } 405 }
399 406
400 /* init workqueue */ 407 setup_timer(&sony_laptop_input.release_key_timer,
401 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); 408 do_sony_laptop_release_key, 0);
402 if (!sony_laptop_input.wq) {
403 printk(KERN_ERR DRV_PFX
404 "Unable to create workqueue.\n");
405 error = -ENXIO;
406 goto err_free_kfifo;
407 }
408 409
409 /* input keys */ 410 /* input keys */
410 key_dev = input_allocate_device(); 411 key_dev = input_allocate_device();
411 if (!key_dev) { 412 if (!key_dev) {
412 error = -ENOMEM; 413 error = -ENOMEM;
413 goto err_destroy_wq; 414 goto err_free_kfifo;
414 } 415 }
415 416
416 key_dev->name = "Sony Vaio Keys"; 417 key_dev->name = "Sony Vaio Keys";
@@ -419,18 +420,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
419 key_dev->dev.parent = &acpi_device->dev; 420 key_dev->dev.parent = &acpi_device->dev;
420 421
421 /* Initialize the Input Drivers: special keys */ 422 /* Initialize the Input Drivers: special keys */
422 set_bit(EV_KEY, key_dev->evbit); 423 input_set_capability(key_dev, EV_MSC, MSC_SCAN);
423 set_bit(EV_MSC, key_dev->evbit); 424
424 set_bit(MSC_SCAN, key_dev->mscbit); 425 __set_bit(EV_KEY, key_dev->evbit);
425 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 426 key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
426 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 427 key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
427 key_dev->keycode = &sony_laptop_input_keycode_map; 428 key_dev->keycode = &sony_laptop_input_keycode_map;
428 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++)
429 if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { 430 __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
430 set_bit(sony_laptop_input_keycode_map[i], 431 __clear_bit(KEY_RESERVED, key_dev->keybit);
431 key_dev->keybit);
432 }
433 }
434 432
435 error = input_register_device(key_dev); 433 error = input_register_device(key_dev);
436 if (error) 434 if (error)
@@ -450,9 +448,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
450 jog_dev->id.vendor = PCI_VENDOR_ID_SONY; 448 jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
451 key_dev->dev.parent = &acpi_device->dev; 449 key_dev->dev.parent = &acpi_device->dev;
452 450
453 jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 451 input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
454 jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); 452 input_set_capability(jog_dev, EV_REL, REL_WHEEL);
455 jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
456 453
457 error = input_register_device(jog_dev); 454 error = input_register_device(jog_dev);
458 if (error) 455 if (error)
@@ -473,9 +470,6 @@ err_unregister_keydev:
473err_free_keydev: 470err_free_keydev:
474 input_free_device(key_dev); 471 input_free_device(key_dev);
475 472
476err_destroy_wq:
477 destroy_workqueue(sony_laptop_input.wq);
478
479err_free_kfifo: 473err_free_kfifo:
480 kfifo_free(&sony_laptop_input.fifo); 474 kfifo_free(&sony_laptop_input.fifo);
481 475
@@ -486,12 +480,23 @@ err_dec_users:
486 480
487static void sony_laptop_remove_input(void) 481static void sony_laptop_remove_input(void)
488{ 482{
489 /* 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 */
490 if (!atomic_dec_and_test(&sony_laptop_input.users)) 486 if (!atomic_dec_and_test(&sony_laptop_input.users))
491 return; 487 return;
492 488
493 /* flush workqueue first */ 489 del_timer_sync(&sony_laptop_input.release_key_timer);
494 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 }
495 500
496 /* destroy input devs */ 501 /* destroy input devs */
497 input_unregister_device(sony_laptop_input.key_dev); 502 input_unregister_device(sony_laptop_input.key_dev);
@@ -502,7 +507,6 @@ static void sony_laptop_remove_input(void)
502 sony_laptop_input.jog_dev = NULL; 507 sony_laptop_input.jog_dev = NULL;
503 } 508 }
504 509
505 destroy_workqueue(sony_laptop_input.wq);
506 kfifo_free(&sony_laptop_input.fifo); 510 kfifo_free(&sony_laptop_input.fifo);
507} 511}
508 512
@@ -1288,9 +1292,13 @@ static int sony_nc_add(struct acpi_device *device)
1288 "controlled by ACPI video driver\n"); 1292 "controlled by ACPI video driver\n");
1289 } 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",
1290 &handle))) { 1294 &handle))) {
1295 struct backlight_properties props;
1296 memset(&props, 0, sizeof(struct backlight_properties));
1297 props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
1291 sony_backlight_device = backlight_device_register("sony", NULL, 1298 sony_backlight_device = backlight_device_register("sony", NULL,
1292 NULL, 1299 NULL,
1293 &sony_backlight_ops); 1300 &sony_backlight_ops,
1301 &props);
1294 1302
1295 if (IS_ERR(sony_backlight_device)) { 1303 if (IS_ERR(sony_backlight_device)) {
1296 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); 1304 printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
@@ -1299,8 +1307,6 @@ static int sony_nc_add(struct acpi_device *device)
1299 sony_backlight_device->props.brightness = 1307 sony_backlight_device->props.brightness =
1300 sony_backlight_get_brightness 1308 sony_backlight_get_brightness
1301 (sony_backlight_device); 1309 (sony_backlight_device);
1302 sony_backlight_device->props.max_brightness =
1303 SONY_MAX_BRIGHTNESS - 1;
1304 } 1310 }
1305 1311
1306 } 1312 }