aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r--drivers/misc/sony-laptop.c212
1 files changed, 112 insertions, 100 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index e67189a361a2..2d05d5b7e125 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -54,6 +54,64 @@ module_param(debug, int, 0);
54MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help " 54MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
55 "the development of this driver"); 55 "the development of this driver");
56 56
57/*********** Platform Device ***********/
58
59static atomic_t sony_pf_users = ATOMIC_INIT(0);
60static struct platform_driver sony_pf_driver = {
61 .driver = {
62 .name = "sony-laptop",
63 .owner = THIS_MODULE,
64 }
65};
66static struct platform_device *sony_pf_device;
67
68static int sony_pf_add(void)
69{
70 int ret = 0;
71
72 /* don't run again if already initialized */
73 if (atomic_add_return(1, &sony_pf_users) > 1)
74 return 0;
75
76 ret = platform_driver_register(&sony_pf_driver);
77 if (ret)
78 goto out;
79
80 sony_pf_device = platform_device_alloc("sony-laptop", -1);
81 if (!sony_pf_device) {
82 ret = -ENOMEM;
83 goto out_platform_registered;
84 }
85
86 ret = platform_device_add(sony_pf_device);
87 if (ret)
88 goto out_platform_alloced;
89
90 return 0;
91
92 out_platform_alloced:
93 platform_device_put(sony_pf_device);
94 sony_pf_device = NULL;
95 out_platform_registered:
96 platform_driver_unregister(&sony_pf_driver);
97 out:
98 atomic_dec(&sony_pf_users);
99 return ret;
100}
101
102static void sony_pf_remove(void)
103{
104 /* deregister only after the last user has gone */
105 if (!atomic_dec_and_test(&sony_pf_users))
106 return;
107
108 platform_device_del(sony_pf_device);
109 platform_device_put(sony_pf_device);
110 platform_driver_unregister(&sony_pf_driver);
111}
112
113/*********** SNC (SNY5001) Device ***********/
114
57static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *, 115static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
58 char *); 116 char *);
59static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *, 117static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
@@ -279,104 +337,6 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
279 return count; 337 return count;
280} 338}
281 339
282/*
283 * Platform device
284 */
285static struct platform_driver sncpf_driver = {
286 .driver = {
287 .name = "sony-laptop",
288 .owner = THIS_MODULE,
289 }
290};
291static struct platform_device *sncpf_device;
292
293static int sony_nc_pf_add(void)
294{
295 acpi_handle handle;
296 struct sony_nc_value *item;
297 int ret = 0;
298
299 ret = platform_driver_register(&sncpf_driver);
300 if (ret)
301 goto out;
302
303 sncpf_device = platform_device_alloc("sony-laptop", -1);
304 if (!sncpf_device) {
305 ret = -ENOMEM;
306 goto out_platform_registered;
307 }
308
309 ret = platform_device_add(sncpf_device);
310 if (ret)
311 goto out_platform_alloced;
312
313 for (item = sony_nc_values; item->name; ++item) {
314
315 if (!debug && item->debug)
316 continue;
317
318 /* find the available acpiget as described in the DSDT */
319 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
320 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
321 *item->acpiget,
322 &handle))) {
323 if (debug)
324 printk(LOG_PFX "Found %s getter: %s\n",
325 item->name, *item->acpiget);
326 item->devattr.attr.mode |= S_IRUGO;
327 break;
328 }
329 }
330
331 /* find the available acpiset as described in the DSDT */
332 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
333 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
334 *item->acpiset,
335 &handle))) {
336 if (debug)
337 printk(LOG_PFX "Found %s setter: %s\n",
338 item->name, *item->acpiset);
339 item->devattr.attr.mode |= S_IWUSR;
340 break;
341 }
342 }
343
344 if (item->devattr.attr.mode != 0) {
345 ret =
346 device_create_file(&sncpf_device->dev,
347 &item->devattr);
348 if (ret)
349 goto out_sysfs;
350 }
351 }
352
353 return 0;
354
355 out_sysfs:
356 for (item = sony_nc_values; item->name; ++item) {
357 device_remove_file(&sncpf_device->dev, &item->devattr);
358 }
359 platform_device_del(sncpf_device);
360 out_platform_alloced:
361 platform_device_put(sncpf_device);
362 out_platform_registered:
363 platform_driver_unregister(&sncpf_driver);
364 out:
365 return ret;
366}
367
368static void sony_nc_pf_remove(void)
369{
370 struct sony_nc_value *item;
371
372 for (item = sony_nc_values; item->name; ++item) {
373 device_remove_file(&sncpf_device->dev, &item->devattr);
374 }
375
376 platform_device_del(sncpf_device);
377 platform_device_put(sncpf_device);
378 platform_driver_unregister(&sncpf_driver);
379}
380 340
381/* 341/*
382 * Backlight device 342 * Backlight device
@@ -455,6 +415,7 @@ static int sony_nc_add(struct acpi_device *device)
455 acpi_status status; 415 acpi_status status;
456 int result = 0; 416 int result = 0;
457 acpi_handle handle; 417 acpi_handle handle;
418 struct sony_nc_value *item;
458 419
459 sony_nc_acpi_device = device; 420 sony_nc_acpi_device = device;
460 421
@@ -497,13 +458,59 @@ static int sony_nc_add(struct acpi_device *device)
497 458
498 } 459 }
499 460
500 if (sony_nc_pf_add()) 461 if (sony_pf_add())
501 goto outbacklight; 462 goto outbacklight;
502 463
464 /* create sony_pf sysfs attributes related to the SNC device */
465 for (item = sony_nc_values; item->name; ++item) {
466
467 if (!debug && item->debug)
468 continue;
469
470 /* find the available acpiget as described in the DSDT */
471 for (; item->acpiget && *item->acpiget; ++item->acpiget) {
472 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
473 *item->acpiget,
474 &handle))) {
475 if (debug)
476 printk(LOG_PFX "Found %s getter: %s\n",
477 item->name, *item->acpiget);
478 item->devattr.attr.mode |= S_IRUGO;
479 break;
480 }
481 }
482
483 /* find the available acpiset as described in the DSDT */
484 for (; item->acpiset && *item->acpiset; ++item->acpiset) {
485 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
486 *item->acpiset,
487 &handle))) {
488 if (debug)
489 printk(LOG_PFX "Found %s setter: %s\n",
490 item->name, *item->acpiset);
491 item->devattr.attr.mode |= S_IWUSR;
492 break;
493 }
494 }
495
496 if (item->devattr.attr.mode != 0) {
497 result =
498 device_create_file(&sony_pf_device->dev,
499 &item->devattr);
500 if (result)
501 goto out_sysfs;
502 }
503 }
504
503 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n"); 505 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
504 506
505 return 0; 507 return 0;
506 508
509 out_sysfs:
510 for (item = sony_nc_values; item->name; ++item) {
511 device_remove_file(&sony_pf_device->dev, &item->devattr);
512 }
513 sony_pf_remove();
507 outbacklight: 514 outbacklight:
508 if (sony_backlight_device) 515 if (sony_backlight_device)
509 backlight_device_unregister(sony_backlight_device); 516 backlight_device_unregister(sony_backlight_device);
@@ -520,6 +527,7 @@ static int sony_nc_add(struct acpi_device *device)
520static int sony_nc_remove(struct acpi_device *device, int type) 527static int sony_nc_remove(struct acpi_device *device, int type)
521{ 528{
522 acpi_status status; 529 acpi_status status;
530 struct sony_nc_value *item;
523 531
524 if (sony_backlight_device) 532 if (sony_backlight_device)
525 backlight_device_unregister(sony_backlight_device); 533 backlight_device_unregister(sony_backlight_device);
@@ -532,7 +540,11 @@ static int sony_nc_remove(struct acpi_device *device, int type)
532 if (ACPI_FAILURE(status)) 540 if (ACPI_FAILURE(status))
533 printk(LOG_PFX "unable to remove notify handler\n"); 541 printk(LOG_PFX "unable to remove notify handler\n");
534 542
535 sony_nc_pf_remove(); 543 for (item = sony_nc_values; item->name; ++item) {
544 device_remove_file(&sony_pf_device->dev, &item->devattr);
545 }
546
547 sony_pf_remove();
536 548
537 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n"); 549 printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
538 550