From patchwork Tue Aug 6 22:48:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felipe Contreras X-Patchwork-Id: 2839712 X-Patchwork-Delegate: rui.zhang@intel.com Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9D65DBF535 for ; Tue, 6 Aug 2013 22:52:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 462892025A for ; Tue, 6 Aug 2013 22:52:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1527420257 for ; Tue, 6 Aug 2013 22:52:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756751Ab3HFWwF (ORCPT ); Tue, 6 Aug 2013 18:52:05 -0400 Received: from mail-ob0-f169.google.com ([209.85.214.169]:57389 "EHLO mail-ob0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756693Ab3HFWwD (ORCPT ); Tue, 6 Aug 2013 18:52:03 -0400 Received: by mail-ob0-f169.google.com with SMTP id wc20so2267958obb.14 for ; Tue, 06 Aug 2013 15:52:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=Or4FQZO9f45jZLil0jrARMbp7rBOdsT1Xtbgv5Q9o2w=; b=lWAvUUJuD9l4rbo1RzGl3P09M7Uigj/xsMgAX0xauLCBepzg57bmk9s01XhZcDjJN7 j1CsiTOW63lInCXyfySR22vMX+G3wFkmKnwMeUbp75JcPUFLvTPL5gn/kwJWo/jDGp6u GFZILXJMUJL3eZ//qGTBzDVtVSIObvXkl/VrGuqgUUJLWbxuMZKBkzyYwi2f+sVQKgI8 fsKrH7IyGeCpqY7Zw4sziILDs5F0+jKS496BC31+jF/eyTIYAVya81yV9vhW9ulxqaIF G7pxB4vpurGvBDxH7qsLk2CrPLtlaCSG4TIgaOIvCQoT6oKTpmG6wf77B0jwNuuXcfcD 8S+g== X-Received: by 10.60.142.103 with SMTP id rv7mr410082oeb.13.1375829522961; Tue, 06 Aug 2013 15:52:02 -0700 (PDT) Received: from localhost (187-162-140-241.static.axtel.net. [187.162.140.241]) by mx.google.com with ESMTPSA id r4sm4519146oem.3.2013.08.06.15.52.01 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 06 Aug 2013 15:52:02 -0700 (PDT) From: Felipe Contreras To: linux-pm@vger.kernel.org Cc: Zhang Rui , Eduardo Valentin , linux-kernel@vger.kernel.org, Felipe Contreras Subject: [PATCH] thermal: new asus driver Date: Tue, 6 Aug 2013 17:48:20 -0500 Message-Id: <1375829300-14081-1-git-send-email-felipe.contreras@gmail.com> X-Mailer: git-send-email 1.8.3.267.gbb4989f Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Simple driver to enable control of the fan in ASUS laptops. So far this has only been tested in ASUS Zenbook Prime UX31A, but according to some online reference [1], it should work in other models as well. Another source was a patch acpi4asus-user's mailing list [2]. [1] http://forum.notebookreview.com/asus/705656-fan-control-asus-prime-ux31-ux31a-ux32a-ux32vd.html [2] http://www.mail-archive.com/acpi4asus-user@lists.sourceforge.net/msg00065.html Signed-off-by: Felipe Contreras --- I've never implemented a driver like this, so I've no idea if this is the right way to do it. drivers/thermal/Kconfig | 7 ++++ drivers/thermal/Makefile | 1 + drivers/thermal/asus_thermal.c | 94 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 drivers/thermal/asus_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index e988c81..0c5b624 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -184,4 +184,11 @@ menu "Texas Instruments thermal drivers" source "drivers/thermal/ti-soc-thermal/Kconfig" endmenu +config ASUS_THERMAL + tristate "ASUS thermal driver" + depends on THERMAL + depends on X86 + help + Enables control of the fan in ASUS laptops. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 67184a2..ab4ea6f 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ +obj-$(CONFIG_ASUS_THERMAL) += asus_thermal.o diff --git a/drivers/thermal/asus_thermal.c b/drivers/thermal/asus_thermal.c new file mode 100644 index 0000000..eceeee3 --- /dev/null +++ b/drivers/thermal/asus_thermal.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Felipe Contreras "); +MODULE_DESCRIPTION("ASUS fan driver"); +MODULE_LICENSE("GPL"); + +static struct thermal_cooling_device *cdev; + +static int fan_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + *state = 0xff; + return 0; +} + +static int fan_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct acpi_object_list params; + union acpi_object in_objs[1]; + unsigned long long value; + acpi_status r; + + params.count = ARRAY_SIZE(in_objs); + params.pointer = in_objs; + in_objs[0].type = ACPI_TYPE_INTEGER; + in_objs[0].integer.value = 0; + + r = acpi_evaluate_integer(NULL, "\\_TZ.RFAN", ¶ms, &value); + if (r != AE_OK) + return r; + + *state = value; + + return 0; +} + +static int fan_set(struct thermal_cooling_device *cdev, int fan, int speed) +{ + struct acpi_object_list params; + union acpi_object in_objs[2]; + unsigned long long value; + + params.count = ARRAY_SIZE(in_objs); + params.pointer = in_objs; + in_objs[0].type = ACPI_TYPE_INTEGER; + in_objs[0].integer.value = fan; + in_objs[1].type = ACPI_TYPE_INTEGER; + in_objs[1].integer.value = speed; + + return acpi_evaluate_integer(NULL, "\\_SB.PCI0.LPCB.EC0.SFNV", ¶ms, &value); +} + +static int fan_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + return fan_set(cdev, 1, state); +} + +static int fan_set_auto(struct thermal_cooling_device *cdev) +{ + return fan_set(cdev, 0, 0); +} + +static const struct thermal_cooling_device_ops fan_cooling_ops = { + .get_max_state = fan_get_max_state, + .get_cur_state = fan_get_cur_state, + .set_cur_state = fan_set_cur_state, +}; + +static int __init fan_init(void) +{ + if (strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "ASUSTeK COMPUTER INC.")) + return -ENODEV; + cdev = thermal_cooling_device_register("Fan", NULL, &fan_cooling_ops); + if (IS_ERR(cdev)) + return PTR_ERR(cdev); + fan_set_auto(cdev); + return 0; +} + +static void __exit fan_exit(void) +{ + fan_set_auto(cdev); + thermal_cooling_device_unregister(cdev); +} + +module_init(fan_init); +module_exit(fan_exit);