aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier Achirica <jachirica@gmail.com>2014-03-20 19:01:16 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2014-04-06 12:58:12 -0400
commitc62f15395c780fff606cfec23d66417a80a5ad81 (patch)
tree5a94e892b5686b12dee564c31345ebb8d84ca9d7
parent2a26f3415865a9540b0b8a93455eeeea90a98983 (diff)
sony-laptop: add fan speed regulation function
Rework error exit logic by Mattia Dongili. Signed-off-by: Javier Achirica <jachirica@gmail.com> Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
-rw-r--r--drivers/platform/x86/sony-laptop.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 9620285cb9af..7b5a56d59bac 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -164,6 +164,9 @@ static int __sony_nc_gfx_switch_status_get(void);
164static int sony_nc_highspeed_charging_setup(struct platform_device *pd); 164static int sony_nc_highspeed_charging_setup(struct platform_device *pd);
165static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); 165static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd);
166 166
167static int sony_nc_fanspeed_setup(struct platform_device *pd);
168static void sony_nc_fanspeed_cleanup(struct platform_device *pd);
169
167static int sony_nc_usb_charge_setup(struct platform_device *pd); 170static int sony_nc_usb_charge_setup(struct platform_device *pd);
168static void sony_nc_usb_charge_cleanup(struct platform_device *pd); 171static void sony_nc_usb_charge_cleanup(struct platform_device *pd);
169 172
@@ -1391,6 +1394,12 @@ static void sony_nc_function_setup(struct acpi_device *device,
1391 pr_err("couldn't set up keyboard backlight function (%d)\n", 1394 pr_err("couldn't set up keyboard backlight function (%d)\n",
1392 result); 1395 result);
1393 break; 1396 break;
1397 case 0x0149:
1398 result = sony_nc_fanspeed_setup(pf_device);
1399 if (result)
1400 pr_err("couldn't set up fan speed function (%d)\n",
1401 result);
1402 break;
1394 case 0x0155: 1403 case 0x0155:
1395 result = sony_nc_usb_charge_setup(pf_device); 1404 result = sony_nc_usb_charge_setup(pf_device);
1396 if (result) 1405 if (result)
@@ -1467,6 +1476,9 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
1467 case 0x0163: 1476 case 0x0163:
1468 sony_nc_kbd_backlight_cleanup(pd, handle); 1477 sony_nc_kbd_backlight_cleanup(pd, handle);
1469 break; 1478 break;
1479 case 0x0149:
1480 sony_nc_fanspeed_cleanup(pd);
1481 break;
1470 case 0x0155: 1482 case 0x0155:
1471 sony_nc_usb_charge_cleanup(pd); 1483 sony_nc_usb_charge_cleanup(pd);
1472 break; 1484 break;
@@ -2564,6 +2576,113 @@ static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd)
2564 } 2576 }
2565} 2577}
2566 2578
2579/* fan speed function */
2580static struct device_attribute *fan_handle, *hsf_handle;
2581
2582static ssize_t sony_nc_hsfan_store(struct device *dev,
2583 struct device_attribute *attr,
2584 const char *buffer, size_t count)
2585{
2586 unsigned int result;
2587 unsigned long value;
2588
2589 if (count > 31)
2590 return -EINVAL;
2591
2592 if (kstrtoul(buffer, 10, &value) || value > 1)
2593 return -EINVAL;
2594
2595 if (sony_call_snc_handle(0x0149, value << 0x10 | 0x0200, &result))
2596 return -EIO;
2597
2598 return count;
2599}
2600
2601static ssize_t sony_nc_hsfan_show(struct device *dev,
2602 struct device_attribute *attr, char *buffer)
2603{
2604 unsigned int result;
2605
2606 if (sony_call_snc_handle(0x0149, 0x0100, &result))
2607 return -EIO;
2608
2609 return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01);
2610}
2611
2612static ssize_t sony_nc_fanspeed_show(struct device *dev,
2613 struct device_attribute *attr, char *buffer)
2614{
2615 unsigned int result;
2616
2617 if (sony_call_snc_handle(0x0149, 0x0300, &result))
2618 return -EIO;
2619
2620 return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0xff);
2621}
2622
2623static int sony_nc_fanspeed_setup(struct platform_device *pd)
2624{
2625 unsigned int result;
2626
2627 fan_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2628 if (!fan_handle)
2629 return -ENOMEM;
2630
2631 hsf_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
2632 if (!hsf_handle) {
2633 result = -ENOMEM;
2634 goto out_hsf_handle_alloc;
2635 }
2636
2637 sysfs_attr_init(&fan_handle->attr);
2638 fan_handle->attr.name = "fanspeed";
2639 fan_handle->attr.mode = S_IRUGO;
2640 fan_handle->show = sony_nc_fanspeed_show;
2641 fan_handle->store = NULL;
2642
2643 sysfs_attr_init(&hsf_handle->attr);
2644 hsf_handle->attr.name = "fan_forced";
2645 hsf_handle->attr.mode = S_IRUGO | S_IWUSR;
2646 hsf_handle->show = sony_nc_hsfan_show;
2647 hsf_handle->store = sony_nc_hsfan_store;
2648
2649 result = device_create_file(&pd->dev, fan_handle);
2650 if (result)
2651 goto out_fan_handle;
2652
2653 result = device_create_file(&pd->dev, hsf_handle);
2654 if (result)
2655 goto out_hsf_handle;
2656
2657 return 0;
2658
2659out_hsf_handle:
2660 device_remove_file(&pd->dev, fan_handle);
2661
2662out_fan_handle:
2663 kfree(hsf_handle);
2664 hsf_handle = NULL;
2665
2666out_hsf_handle_alloc:
2667 kfree(fan_handle);
2668 fan_handle = NULL;
2669 return result;
2670}
2671
2672static void sony_nc_fanspeed_cleanup(struct platform_device *pd)
2673{
2674 if (fan_handle) {
2675 device_remove_file(&pd->dev, fan_handle);
2676 kfree(fan_handle);
2677 fan_handle = NULL;
2678 }
2679 if (hsf_handle) {
2680 device_remove_file(&pd->dev, hsf_handle);
2681 kfree(hsf_handle);
2682 hsf_handle = NULL;
2683 }
2684}
2685
2567/* USB charge function */ 2686/* USB charge function */
2568static struct device_attribute *uc_handle; 2687static struct device_attribute *uc_handle;
2569 2688