|
@@ -54,6 +54,64 @@ module_param(debug, int, 0);
|
|
|
MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
|
|
|
"the development of this driver");
|
|
|
|
|
|
+/*********** Platform Device ***********/
|
|
|
+
|
|
|
+static atomic_t sony_pf_users = ATOMIC_INIT(0);
|
|
|
+static struct platform_driver sony_pf_driver = {
|
|
|
+ .driver = {
|
|
|
+ .name = "sony-laptop",
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ }
|
|
|
+};
|
|
|
+static struct platform_device *sony_pf_device;
|
|
|
+
|
|
|
+static int sony_pf_add(void)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ /* don't run again if already initialized */
|
|
|
+ if (atomic_add_return(1, &sony_pf_users) > 1)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ ret = platform_driver_register(&sony_pf_driver);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ sony_pf_device = platform_device_alloc("sony-laptop", -1);
|
|
|
+ if (!sony_pf_device) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out_platform_registered;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = platform_device_add(sony_pf_device);
|
|
|
+ if (ret)
|
|
|
+ goto out_platform_alloced;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ out_platform_alloced:
|
|
|
+ platform_device_put(sony_pf_device);
|
|
|
+ sony_pf_device = NULL;
|
|
|
+ out_platform_registered:
|
|
|
+ platform_driver_unregister(&sony_pf_driver);
|
|
|
+ out:
|
|
|
+ atomic_dec(&sony_pf_users);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void sony_pf_remove(void)
|
|
|
+{
|
|
|
+ /* deregister only after the last user has gone */
|
|
|
+ if (!atomic_dec_and_test(&sony_pf_users))
|
|
|
+ return;
|
|
|
+
|
|
|
+ platform_device_del(sony_pf_device);
|
|
|
+ platform_device_put(sony_pf_device);
|
|
|
+ platform_driver_unregister(&sony_pf_driver);
|
|
|
+}
|
|
|
+
|
|
|
+/*********** SNC (SNY5001) Device ***********/
|
|
|
+
|
|
|
static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
|
|
|
char *);
|
|
|
static 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,
|
|
|
return count;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Platform device
|
|
|
- */
|
|
|
-static struct platform_driver sncpf_driver = {
|
|
|
- .driver = {
|
|
|
- .name = "sony-laptop",
|
|
|
- .owner = THIS_MODULE,
|
|
|
- }
|
|
|
-};
|
|
|
-static struct platform_device *sncpf_device;
|
|
|
-
|
|
|
-static int sony_nc_pf_add(void)
|
|
|
-{
|
|
|
- acpi_handle handle;
|
|
|
- struct sony_nc_value *item;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- ret = platform_driver_register(&sncpf_driver);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- sncpf_device = platform_device_alloc("sony-laptop", -1);
|
|
|
- if (!sncpf_device) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out_platform_registered;
|
|
|
- }
|
|
|
-
|
|
|
- ret = platform_device_add(sncpf_device);
|
|
|
- if (ret)
|
|
|
- goto out_platform_alloced;
|
|
|
-
|
|
|
- for (item = sony_nc_values; item->name; ++item) {
|
|
|
-
|
|
|
- if (!debug && item->debug)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* find the available acpiget as described in the DSDT */
|
|
|
- for (; item->acpiget && *item->acpiget; ++item->acpiget) {
|
|
|
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
|
|
|
- *item->acpiget,
|
|
|
- &handle))) {
|
|
|
- if (debug)
|
|
|
- printk(LOG_PFX "Found %s getter: %s\n",
|
|
|
- item->name, *item->acpiget);
|
|
|
- item->devattr.attr.mode |= S_IRUGO;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* find the available acpiset as described in the DSDT */
|
|
|
- for (; item->acpiset && *item->acpiset; ++item->acpiset) {
|
|
|
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
|
|
|
- *item->acpiset,
|
|
|
- &handle))) {
|
|
|
- if (debug)
|
|
|
- printk(LOG_PFX "Found %s setter: %s\n",
|
|
|
- item->name, *item->acpiset);
|
|
|
- item->devattr.attr.mode |= S_IWUSR;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (item->devattr.attr.mode != 0) {
|
|
|
- ret =
|
|
|
- device_create_file(&sncpf_device->dev,
|
|
|
- &item->devattr);
|
|
|
- if (ret)
|
|
|
- goto out_sysfs;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
- out_sysfs:
|
|
|
- for (item = sony_nc_values; item->name; ++item) {
|
|
|
- device_remove_file(&sncpf_device->dev, &item->devattr);
|
|
|
- }
|
|
|
- platform_device_del(sncpf_device);
|
|
|
- out_platform_alloced:
|
|
|
- platform_device_put(sncpf_device);
|
|
|
- out_platform_registered:
|
|
|
- platform_driver_unregister(&sncpf_driver);
|
|
|
- out:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static void sony_nc_pf_remove(void)
|
|
|
-{
|
|
|
- struct sony_nc_value *item;
|
|
|
-
|
|
|
- for (item = sony_nc_values; item->name; ++item) {
|
|
|
- device_remove_file(&sncpf_device->dev, &item->devattr);
|
|
|
- }
|
|
|
-
|
|
|
- platform_device_del(sncpf_device);
|
|
|
- platform_device_put(sncpf_device);
|
|
|
- platform_driver_unregister(&sncpf_driver);
|
|
|
-}
|
|
|
|
|
|
/*
|
|
|
* Backlight device
|
|
@@ -455,6 +415,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
acpi_status status;
|
|
|
int result = 0;
|
|
|
acpi_handle handle;
|
|
|
+ struct sony_nc_value *item;
|
|
|
|
|
|
sony_nc_acpi_device = device;
|
|
|
|
|
@@ -497,13 +458,59 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
|
|
|
}
|
|
|
|
|
|
- if (sony_nc_pf_add())
|
|
|
+ if (sony_pf_add())
|
|
|
goto outbacklight;
|
|
|
|
|
|
+ /* create sony_pf sysfs attributes related to the SNC device */
|
|
|
+ for (item = sony_nc_values; item->name; ++item) {
|
|
|
+
|
|
|
+ if (!debug && item->debug)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* find the available acpiget as described in the DSDT */
|
|
|
+ for (; item->acpiget && *item->acpiget; ++item->acpiget) {
|
|
|
+ if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
|
|
|
+ *item->acpiget,
|
|
|
+ &handle))) {
|
|
|
+ if (debug)
|
|
|
+ printk(LOG_PFX "Found %s getter: %s\n",
|
|
|
+ item->name, *item->acpiget);
|
|
|
+ item->devattr.attr.mode |= S_IRUGO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* find the available acpiset as described in the DSDT */
|
|
|
+ for (; item->acpiset && *item->acpiset; ++item->acpiset) {
|
|
|
+ if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
|
|
|
+ *item->acpiset,
|
|
|
+ &handle))) {
|
|
|
+ if (debug)
|
|
|
+ printk(LOG_PFX "Found %s setter: %s\n",
|
|
|
+ item->name, *item->acpiset);
|
|
|
+ item->devattr.attr.mode |= S_IWUSR;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item->devattr.attr.mode != 0) {
|
|
|
+ result =
|
|
|
+ device_create_file(&sony_pf_device->dev,
|
|
|
+ &item->devattr);
|
|
|
+ if (result)
|
|
|
+ goto out_sysfs;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
+ out_sysfs:
|
|
|
+ for (item = sony_nc_values; item->name; ++item) {
|
|
|
+ device_remove_file(&sony_pf_device->dev, &item->devattr);
|
|
|
+ }
|
|
|
+ sony_pf_remove();
|
|
|
outbacklight:
|
|
|
if (sony_backlight_device)
|
|
|
backlight_device_unregister(sony_backlight_device);
|
|
@@ -520,6 +527,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
static int sony_nc_remove(struct acpi_device *device, int type)
|
|
|
{
|
|
|
acpi_status status;
|
|
|
+ struct sony_nc_value *item;
|
|
|
|
|
|
if (sony_backlight_device)
|
|
|
backlight_device_unregister(sony_backlight_device);
|
|
@@ -532,7 +540,11 @@ static int sony_nc_remove(struct acpi_device *device, int type)
|
|
|
if (ACPI_FAILURE(status))
|
|
|
printk(LOG_PFX "unable to remove notify handler\n");
|
|
|
|
|
|
- sony_nc_pf_remove();
|
|
|
+ for (item = sony_nc_values; item->name; ++item) {
|
|
|
+ device_remove_file(&sony_pf_device->dev, &item->devattr);
|
|
|
+ }
|
|
|
+
|
|
|
+ sony_pf_remove();
|
|
|
|
|
|
printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
|
|
|
|