* [PATCH 0/8] toshiba_acpi: New features added and a fix
@ 2013-11-05 3:48 Azael Avalos
2013-11-05 3:48 ` [PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI) Azael Avalos
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Up for review, the following patch series add new features
found on newer Toshiba laptops.
The first two fix an illumination detection bug, so consider
applying those to stable.
The rest just add support for touchpad, accelerometer axes,
keyboard backlight and ECO led, plus platform support, bumping
the version to 0.20.
These apply cleanly to Matthew's platform tree and with
just some fuzz to next tree.
[PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI)
[PATCH 2/8] toshiba_acpi: Adapt illumination_* code to use the new SCI
[PATCH 3/8] toshiba_acpi: Add platform support
[PATCH 4/8] toshiba_acpi: Add kbd backlight support and sysfs files
[PATCH 5/8] toshiba_acpi: Add ECO led support
[PATCH 6/8] toshiba_acpi: Add accelerometer support
[PATCH 7/8] toshiba_acpi: Add touchpad enable/disable support
[PATCH 8/8] toshiba_acpi: Update version and copyright information
Saludos
Azael
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI)
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 2/8] toshiba_acpi: Adapt illumination_* code to use the new SCI Azael Avalos
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
The SCI stands for System Configuration Interface and
it is supposed to be uniform across all their
models.
This patch introduces four new calls, sci_open, sci_close
sci_read and sci_write, along with its definitions and
return codes.
The HCI_ prefix has been removed from all return codes,
since they are shared among the HCI and the SCI.
More information about the SCI can be found at
Jonathan Buzzard's website [1].
[1] http://www.buzzard.me.uk/toshiba/docs.html
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 146 +++++++++++++++++++++++++++---------
1 file changed, 112 insertions(+), 34 deletions(-)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index eb3467e..1e580dd 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -71,27 +71,37 @@ MODULE_LICENSE("GPL");
/* Toshiba ACPI method paths */
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
-/* Toshiba HCI interface definitions
+/* TCI - Toshiba Configuration Interface definitions
*
- * HCI is Toshiba's "Hardware Control Interface" which is supposed to
- * be uniform across all their models. Ideally we would just call
- * dedicated ACPI methods instead of using this primitive interface.
- * However the ACPI methods seem to be incomplete in some areas (for
- * example they allow setting, but not reading, the LCD brightness value),
+ * This configuration interface is composed by the HCI (Hardware Configuration
+ * Interface) and the SCI (Software Configuration Interface), which are
+ * supposed to be uniform across all their models. Ideally we would just call
+ * dedicated ACPI methods instead of using these primitive interfaces.
+ * However the ACPI methods seem to be incomplete in some areas (for example
+ * they allow setting, but not reading, the LCD brightness value),
* so this is still useful.
*/
#define HCI_WORDS 6
/* operations */
-#define HCI_SET 0xff00
+#define SCI_OPEN 0xf100
+#define SCI_CLOSE 0xf200
+#define SCI_GET 0xf300
+#define SCI_SET 0xf400
#define HCI_GET 0xfe00
+#define HCI_SET 0xff00
/* return codes */
-#define HCI_SUCCESS 0x0000
-#define HCI_FAILURE 0x1000
-#define HCI_NOT_SUPPORTED 0x8000
-#define HCI_EMPTY 0x8c00
+#define SUCCESS 0x0000
+#define OPEN_CLOSE_SUCCESS 0x0044
+#define FAILURE 0x1000
+#define NOT_SUPPORTED 0x8000
+#define ALREADY_OPEN 0x8100
+#define NOT_OPENED 0x8200
+#define INPUT_DATA_ERROR 0x8300
+#define NOT_PRESENT 0x8600
+#define FIFO_EMPTY 0x8c00
/* registers */
#define HCI_FAN 0x0004
@@ -251,7 +261,7 @@ static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg,
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status = hci_raw(dev, in, out);
- *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ *result = (status == AE_OK) ? out[0] : FAILURE;
return status;
}
@@ -262,7 +272,7 @@ static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg,
u32 out[HCI_WORDS];
acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
- *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ *result = (status == AE_OK) ? out[0] : FAILURE;
return status;
}
@@ -272,7 +282,7 @@ static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg,
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status = hci_raw(dev, in, out);
- *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ *result = (status == AE_OK) ? out[0] : FAILURE;
return status;
}
@@ -284,7 +294,75 @@ static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg,
acpi_status status = hci_raw(dev, in, out);
*out1 = out[2];
*out2 = out[3];
- *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ *result = (status == AE_OK) ? out[0] : FAILURE;
+ return status;
+}
+
+/* common sci tasks
+ */
+
+static int sci_open(struct toshiba_acpi_dev *dev)
+{
+ u32 in[HCI_WORDS] = { SCI_OPEN, 0, 0, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == FAILURE) {
+ pr_err("ACPI call to open SCI failed\n");
+ return 0;
+ }
+
+ if (out[0] == OPEN_CLOSE_SUCCESS) {
+ return 1;
+ } else if (out[0] == ALREADY_OPEN) {
+ pr_info("Toshiba SCI already opened\n");
+ return 1;
+ } else if (out[0] == NOT_PRESENT) {
+ pr_info("Toshiba SCI is not present\n");
+ }
+
+ return 0;
+}
+
+static void sci_close(struct toshiba_acpi_dev *dev)
+{
+ u32 in[HCI_WORDS] = { SCI_CLOSE, 0, 0, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == FAILURE) {
+ pr_err("ACPI call to close SCI failed\n");
+ return;
+ }
+
+ if (out[0] == OPEN_CLOSE_SUCCESS)
+ return;
+ else if (out[0] == NOT_OPENED)
+ pr_info("Toshiba SCI not opened\n");
+ else if (out[0] == NOT_PRESENT)
+ pr_info("Toshiba SCI is not present\n");
+}
+
+static acpi_status sci_read(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 *out1, u32 *result)
+{
+ u32 in[HCI_WORDS] = { SCI_GET, reg, 0, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(dev, in, out);
+ *out1 = out[2];
+ *result = (ACPI_SUCCESS(status)) ? out[0] : FAILURE;
+ return status;
+}
+
+static acpi_status sci_write(struct toshiba_acpi_dev *dev, u32 reg,
+ u32 in1, u32 *result)
+{
+ u32 in[HCI_WORDS] = { SCI_SET, reg, in1, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(dev, in, out);
+ *result = (ACPI_SUCCESS(status)) ? out[0] : FAILURE;
return status;
}
@@ -399,7 +477,7 @@ static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
value = 0;
value2 = 0;
hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
- if (hci_result == HCI_SUCCESS)
+ if (hci_result == SUCCESS)
*present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
return hci_result;
@@ -429,7 +507,7 @@ static int bt_rfkill_set_block(void *data, bool blocked)
value = (blocked == false);
mutex_lock(&dev->mutex);
- if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) {
+ if (hci_get_radio_state(dev, &radio_state) != SUCCESS) {
err = -EIO;
goto out;
}
@@ -442,7 +520,7 @@ static int bt_rfkill_set_block(void *data, bool blocked)
hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
- if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
+ if (result1 != SUCCESS || result2 != SUCCESS)
err = -EIO;
else
err = 0;
@@ -461,7 +539,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
mutex_lock(&dev->mutex);
hci_result = hci_get_radio_state(dev, &value);
- if (hci_result != HCI_SUCCESS) {
+ if (hci_result != SUCCESS) {
/* Can't do anything useful */
mutex_unlock(&dev->mutex);
return;
@@ -487,7 +565,7 @@ static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled)
hci_read1(dev, HCI_TR_BACKLIGHT, &status, &hci_result);
*enabled = !status;
- return hci_result == HCI_SUCCESS ? 0 : -EIO;
+ return hci_result == SUCCESS ? 0 : -EIO;
}
static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
@@ -496,7 +574,7 @@ static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
u32 value = !enable;
hci_write1(dev, HCI_TR_BACKLIGHT, value, &hci_result);
- return hci_result == HCI_SUCCESS ? 0 : -EIO;
+ return hci_result == SUCCESS ? 0 : -EIO;
}
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
@@ -518,7 +596,7 @@ static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
}
hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
- if (hci_result == HCI_SUCCESS)
+ if (hci_result == SUCCESS)
return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT);
return -EIO;
@@ -571,7 +649,7 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
value = value << HCI_LCD_BRIGHTNESS_SHIFT;
hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
- return hci_result == HCI_SUCCESS ? 0 : -EIO;
+ return hci_result == SUCCESS ? 0 : -EIO;
}
static int set_lcd_status(struct backlight_device *bd)
@@ -620,7 +698,7 @@ static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
u32 hci_result;
hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result);
- return hci_result == HCI_SUCCESS ? 0 : -EIO;
+ return hci_result == SUCCESS ? 0 : -EIO;
}
static int video_proc_show(struct seq_file *m, void *v)
@@ -724,7 +802,7 @@ static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
u32 hci_result;
hci_read1(dev, HCI_FAN, status, &hci_result);
- return hci_result == HCI_SUCCESS ? 0 : -EIO;
+ return hci_result == SUCCESS ? 0 : -EIO;
}
static int fan_proc_show(struct seq_file *m, void *v)
@@ -764,7 +842,7 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
if (sscanf(cmd, " force_on : %i", &value) == 1 &&
value >= 0 && value <= 1) {
hci_write1(dev, HCI_FAN, value, &hci_result);
- if (hci_result != HCI_SUCCESS)
+ if (hci_result != SUCCESS)
return -EIO;
else
dev->force_fan = value;
@@ -792,12 +870,12 @@ static int keys_proc_show(struct seq_file *m, void *v)
if (!dev->key_event_valid && dev->system_event_supported) {
hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
- if (hci_result == HCI_SUCCESS) {
+ if (hci_result == SUCCESS) {
dev->key_event_valid = 1;
dev->last_key_event = value;
- } else if (hci_result == HCI_EMPTY) {
+ } else if (hci_result == FIFO_EMPTY) {
/* better luck next time */
- } else if (hci_result == HCI_NOT_SUPPORTED) {
+ } else if (hci_result == NOT_SUPPORTED) {
/* This is a workaround for an unresolved issue on
* some machines where system events sporadically
* become disabled. */
@@ -1032,7 +1110,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
dev->info_supported = 1;
} else {
hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
- if (hci_result == HCI_SUCCESS)
+ if (hci_result == SUCCESS)
dev->system_event_supported = 1;
}
@@ -1206,7 +1284,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
goto error;
/* Register rfkill switch for Bluetooth */
- if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {
+ if (hci_get_bt_present(dev, &bt_present) == SUCCESS && bt_present) {
dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
&acpi_dev->dev,
RFKILL_TYPE_BLUETOOTH,
@@ -1274,10 +1352,10 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
do {
hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
switch (hci_result) {
- case HCI_SUCCESS:
+ case SUCCESS:
toshiba_acpi_report_hotkey(dev, (int)value);
break;
- case HCI_NOT_SUPPORTED:
+ case NOT_SUPPORTED:
/*
* This is a workaround for an unresolved
* issue on some machines where system events
@@ -1291,7 +1369,7 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
retries--;
break;
}
- } while (retries && hci_result != HCI_EMPTY);
+ } while (retries && hci_result != FIFO_EMPTY);
}
}
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/8] toshiba_acpi: Adapt illumination_* code to use the new SCI
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
2013-11-05 3:48 ` [PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI) Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 3/8] toshiba_acpi: Add platform support Azael Avalos
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Change the toshiba_illumination_* code to use the newly
introduced sci_read and sci_write functions, and in the
process fix toshiba_illumination_available code, since
it was only opening the SCI and the return value was
never checked for errors or actual illumination support.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 91 ++++++++++++++-----------------------
1 file changed, 33 insertions(+), 58 deletions(-)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 1e580dd..d7ecef3 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -111,6 +111,7 @@ MODULE_LICENSE("GPL");
#define HCI_HOTKEY_EVENT 0x001e
#define HCI_LCD_BRIGHTNESS 0x002a
#define HCI_WIRELESS 0x0056
+#define SCI_ILLUMINATION 0x014e
/* field definitions */
#define HCI_HOTKEY_DISABLE 0x0b
@@ -369,18 +370,23 @@ static acpi_status sci_write(struct toshiba_acpi_dev *dev, u32 reg,
/* Illumination support */
static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
{
- u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
+ u32 in[TCI_WORDS] = { SCI_GET, SCI_ILLUMINATION, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
acpi_status status;
- in[0] = 0xf100;
+ if (!sci_open(dev))
+ return 0;
+
status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
+ if (ACPI_FAILURE(status) || out[0] == FAILURE) {
+ pr_err("ACPI call to query Illumination support failed\n");
+ return 0;
+ } else if (out[0] == NOT_SUPPORTED || out[1] != 1) {
pr_info("Illumination device not available\n");
return 0;
}
- in[0] = 0xf400;
- status = hci_raw(dev, in, out);
+ sci_close(dev);
+
return 1;
}
@@ -391,43 +397,23 @@ static void toshiba_illumination_set(struct led_classdev *cdev,
struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
+ u32 state, result;
acpi_status status;
- /* First request : initialize communication. */
- in[0] = 0xf100;
- status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
- pr_info("Illumination device not available\n");
+ if (!sci_open(dev))
return;
- }
- if (brightness) {
- /* Switch the illumination on */
- in[0] = 0xf400;
- in[1] = 0x14e;
- in[2] = 1;
- status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
- pr_info("ACPI call for illumination failed\n");
- return;
- }
- } else {
- /* Switch the illumination off */
- in[0] = 0xf400;
- in[1] = 0x14e;
- in[2] = 0;
- status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
- pr_info("ACPI call for illumination failed.\n");
- return;
- }
+ /* Switch the illumination on/off */
+ state = brightness ? 1 : 0;
+ status = sci_write(dev, SCI_ILLUMINATION, state, &result);
+ if (ACPI_FAILURE(status)) {
+ pr_err("ACPI call for illumination failed\n");
+ return;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Illumination not supported\n");
+ return;
}
-
- /* Last request : close communication. */
- in[0] = 0xf200;
- in[1] = 0;
- in[2] = 0;
- hci_raw(dev, in, out);
+ sci_close(dev);
}
static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
@@ -436,35 +422,24 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
struct toshiba_acpi_dev, led_dev);
u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
+ u32 state, result;
acpi_status status;
- enum led_brightness result;
- /* First request : initialize communication. */
- in[0] = 0xf100;
- status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
- pr_info("Illumination device not available\n");
+ if (!sci_open(dev))
return LED_OFF;
- }
/* Check the illumination */
- in[0] = 0xf300;
- in[1] = 0x14e;
- status = hci_raw(dev, in, out);
- if (ACPI_FAILURE(status)) {
- pr_info("ACPI call for illumination failed.\n");
+ status = sci_read(dev, SCI_ILLUMINATION, &state, &result);
+ if (ACPI_FAILURE(status) || result == INPUT_DATA_ERROR) {
+ pr_err("ACPI call for illumination failed\n");
+ return LED_OFF;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Illumination not supported\n");
return LED_OFF;
}
+ sci_close(dev);
- result = out[2] ? LED_FULL : LED_OFF;
-
- /* Last request : close communication. */
- in[0] = 0xf200;
- in[1] = 0;
- in[2] = 0;
- hci_raw(dev, in, out);
-
- return result;
+ return state ? LED_FULL : LED_OFF;
}
/* Bluetooth rfkill handlers */
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/8] toshiba_acpi: Add platform support
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
2013-11-05 3:48 ` [PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI) Azael Avalos
2013-11-05 3:48 ` [PATCH 2/8] toshiba_acpi: Adapt illumination_* code to use the new SCI Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 4/8] toshiba_acpi: Add kbd backlight support and sysfs files Azael Avalos
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Add platform support and change the backlight
and led devices to register on it instead of the acpi_device.
The use of the platform is to have just one place where to
look for files instead of looking at the current three different
ACPI devices (TOS6200, TOS6208 and TOS1900) and thus making
userspace a bit easier.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index d7ecef3..226e0b5 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -54,6 +54,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/i8042.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
@@ -129,6 +130,7 @@ MODULE_LICENSE("GPL");
struct toshiba_acpi_dev {
struct acpi_device *acpi_dev;
+ struct platform_device *pf_dev;
const char *method_hci;
struct rfkill *bt_rfk;
struct input_dev *hotkey_dev;
@@ -1156,7 +1158,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
props.max_brightness++;
dev->backlight_dev = backlight_device_register("toshiba",
- &dev->acpi_dev->dev,
+ &dev->pf_dev->dev,
dev,
&toshiba_backlight_data,
&props);
@@ -1198,6 +1200,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
if (dev->illumination_supported)
led_classdev_unregister(&dev->led_dev);
+ if (dev->pf_dev)
+ platform_device_unregister(dev->pf_dev);
+
if (toshiba_acpi)
toshiba_acpi = NULL;
@@ -1249,6 +1254,15 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->method_hci = hci_method;
acpi_dev->driver_data = dev;
+ dev->pf_dev = platform_device_register_simple("toshiba", -1, NULL, 0);
+ if (IS_ERR(dev->pf_dev)) {
+ ret = PTR_ERR(dev->pf_dev);
+ pr_err("Unable to register platform device\n");
+ kfree(dev);
+ return ret;
+ }
+ platform_set_drvdata(dev->pf_dev, dev);
+
if (toshiba_acpi_setup_keyboard(dev))
pr_info("Unable to activate hotkeys\n");
@@ -1284,7 +1298,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->led_dev.max_brightness = 1;
dev->led_dev.brightness_set = toshiba_illumination_set;
dev->led_dev.brightness_get = toshiba_illumination_get;
- if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
+ if (!led_classdev_register(&dev->pf_dev->dev, &dev->led_dev))
dev->illumination_supported = 1;
}
@@ -1388,6 +1402,13 @@ static struct acpi_driver toshiba_acpi_driver = {
.drv.pm = &toshiba_acpi_pm,
};
+static struct platform_driver platform_driver = {
+ .driver = {
+ .name = "toshiba",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init toshiba_acpi_init(void)
{
int ret;
@@ -1406,6 +1427,12 @@ static int __init toshiba_acpi_init(void)
return -ENODEV;
}
+ ret = platform_driver_register(&platform_driver);
+ if (ret < 0) {
+ pr_err("Failed to register platform driver: %d\n", ret);
+ return ret;
+ }
+
ret = acpi_bus_register_driver(&toshiba_acpi_driver);
if (ret) {
pr_err("Failed to register ACPI driver: %d\n", ret);
@@ -1418,6 +1445,7 @@ static int __init toshiba_acpi_init(void)
static void __exit toshiba_acpi_exit(void)
{
acpi_bus_unregister_driver(&toshiba_acpi_driver);
+ platform_driver_unregister(&platform_driver);
if (toshiba_proc_dir)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/8] toshiba_acpi: Add kbd backlight support and sysfs files
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
` (2 preceding siblings ...)
2013-11-05 3:48 ` [PATCH 3/8] toshiba_acpi: Add platform support Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 5/8] toshiba_acpi: Add ECO led support Azael Avalos
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Toshiba laptops equiped with an illuminated keyboard
can operate in two different modes: Auto and FN-Z.
The Auto mode turns on the led on keystrokes and
automatically turns it off after some (configurable)
time the last key was pressed.
The FN-Z mode is used to toggle the keyboard led on/off
by userspace.
This patch adds support to set the desired KBD mode and
timeout via sysfs, creates and registers toshiba::kbd_backlight
led device whenever the mode is set to FN-Z.
The acceptable values for mode are: 1 (Auto) and 2 (Fn-Z)
The time values range are: 1-60 seconds
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 242 ++++++++++++++++++++++++++++++++++++
1 file changed, 242 insertions(+)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 226e0b5..f97f942 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -112,7 +112,9 @@ MODULE_LICENSE("GPL");
#define HCI_HOTKEY_EVENT 0x001e
#define HCI_LCD_BRIGHTNESS 0x002a
#define HCI_WIRELESS 0x0056
+#define HCI_KBD_ILLUMINATION 0x0095
#define SCI_ILLUMINATION 0x014e
+#define SCI_KBD_ILLUM_STATUS 0x015c
/* field definitions */
#define HCI_HOTKEY_DISABLE 0x0b
@@ -120,6 +122,7 @@ MODULE_LICENSE("GPL");
#define HCI_LCD_BRIGHTNESS_BITS 3
#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
#define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS)
+#define HCI_MISC_SHIFT 0x10
#define HCI_VIDEO_OUT_LCD 0x1
#define HCI_VIDEO_OUT_CRT 0x2
#define HCI_VIDEO_OUT_TV 0x4
@@ -127,6 +130,8 @@ MODULE_LICENSE("GPL");
#define HCI_WIRELESS_BT_PRESENT 0x0f
#define HCI_WIRELESS_BT_ATTACH 0x40
#define HCI_WIRELESS_BT_POWER 0x80
+#define SCI_KBD_MODE_FNZ 0x1
+#define SCI_KBD_MODE_AUTO 0x2
struct toshiba_acpi_dev {
struct acpi_device *acpi_dev;
@@ -137,10 +142,13 @@ struct toshiba_acpi_dev {
struct work_struct hotkey_work;
struct backlight_device *backlight_dev;
struct led_classdev led_dev;
+ struct led_classdev kbd_led;
int force_fan;
int last_key_event;
int key_event_valid;
+ int kbd_mode;
+ int kbd_time;
unsigned int illumination_supported:1;
unsigned int video_supported:1;
@@ -149,6 +157,9 @@ struct toshiba_acpi_dev {
unsigned int ntfy_supported:1;
unsigned int info_supported:1;
unsigned int tr_backlight_supported:1;
+ unsigned int kbd_illum_supported:1;
+ unsigned int kbd_led_registered:1;
+ unsigned int sysfs_created:1;
struct mutex mutex;
};
@@ -444,6 +455,89 @@ static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
return state ? LED_FULL : LED_OFF;
}
+/* KBD Illumination */
+static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time)
+{
+ u32 result;
+ acpi_status status;
+
+ if (!sci_open(dev))
+ return -EIO;
+
+ status = sci_write(dev, SCI_KBD_ILLUM_STATUS, time, &result);
+ if (ACPI_FAILURE(status) || result == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to set KBD backlight status failed\n");
+ return -EIO;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Keyboard backlight status not supported\n");
+ return -ENODEV;
+ }
+ sci_close(dev);
+
+ return 0;
+}
+
+static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time)
+{
+ u32 result;
+ acpi_status status;
+
+ if (!sci_open(dev))
+ return -EIO;
+
+ status = sci_read(dev, SCI_KBD_ILLUM_STATUS, time, &result);
+ if (ACPI_FAILURE(status) || result == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to get KBD backlight status failed\n");
+ return -EIO;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Keyboard backlight status not supported\n");
+ return -ENODEV;
+ }
+ sci_close(dev);
+
+ return 0;
+}
+
+static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev)
+{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, kbd_led);
+ u32 state, result;
+ acpi_status status;
+
+ /* Check the keyboard backlight state */
+ status = hci_read1(dev, HCI_KBD_ILLUMINATION, &state, &result);
+ if (ACPI_FAILURE(status) || result == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to get the keyboard backlight failed\n");
+ return LED_OFF;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Keyboard backlight not supported\n");
+ return LED_OFF;
+ }
+
+ return state ? LED_FULL : LED_OFF;
+}
+
+static void toshiba_kbd_backlight_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, kbd_led);
+ u32 state, result;
+ acpi_status status;
+
+ /* Set the keyboard backlight state */
+ state = brightness ? 1 : 0;
+ status = hci_write1(dev, HCI_KBD_ILLUMINATION, state, &result);
+ if (ACPI_FAILURE(status) || result == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to set KBD Illumination mode failed\n");
+ return;
+ } else if (result == NOT_SUPPORTED) {
+ pr_info("Keyboard backlight not supported\n");
+ return;
+ }
+}
+
/* Bluetooth rfkill handlers */
static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -967,6 +1061,118 @@ static const struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
+/*
+ * Sysfs files
+ */
+
+static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ int mode = -1;
+ int time = -1;
+
+ if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1))
+ return -EINVAL;
+
+ /* Set the Keyboard Backlight Mode where:
+ * Mode - Auto (2) | FN-Z (1)
+ * Auto - KBD backlight turns off automatically in given time
+ * FN-Z - KBD backlight "toggles" when hotkey pressed
+ */
+ if (mode != -1 && toshiba->kbd_mode != mode) {
+ time = toshiba->kbd_time << HCI_MISC_SHIFT;
+ time = time + toshiba->kbd_mode;
+ if (toshiba_kbd_illum_status_set(toshiba, time) < 0)
+ return -EIO;
+ toshiba->kbd_mode = mode;
+ }
+
+ return count;
+}
+
+static ssize_t toshiba_kbd_bl_mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ u32 time;
+
+ if (toshiba_kbd_illum_status_get(toshiba, &time) < 0)
+ return -EIO;
+
+ return sprintf(buf, "%i\n", time & 0x07);
+}
+
+static ssize_t toshiba_kbd_bl_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ int time = -1;
+
+ if (sscanf(buf, "%i", &time) != 1 && (time < 0 || time > 60))
+ return -EINVAL;
+
+ /* Set the Keyboard Backlight Timeout: 0-60 seconds */
+ if (time != -1 && toshiba->kbd_time != time) {
+ time = time << HCI_MISC_SHIFT;
+ time = (toshiba->kbd_mode == SCI_KBD_MODE_AUTO) ?
+ time + 1 : time + 2;
+ if (toshiba_kbd_illum_status_set(toshiba, time) < 0)
+ return -EIO;
+ toshiba->kbd_time = time >> HCI_MISC_SHIFT;
+ }
+
+ return count;
+}
+
+static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ u32 time;
+
+ if (toshiba_kbd_illum_status_get(toshiba, &time) < 0)
+ return -EIO;
+
+ return sprintf(buf, "%i\n", time >> HCI_MISC_SHIFT);
+}
+
+static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
+ toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
+static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
+ toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store);
+
+static struct attribute *toshiba_attributes[] = {
+ &dev_attr_kbd_backlight_mode.attr,
+ &dev_attr_kbd_backlight_timeout.attr,
+ NULL,
+};
+
+static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct toshiba_acpi_dev *driver = platform_get_drvdata(pdev);
+ bool exists = true;
+
+ if (attr == &dev_attr_kbd_backlight_mode.attr)
+ exists = (driver->kbd_illum_supported) ? true : false;
+ else if (attr == &dev_attr_kbd_backlight_timeout.attr)
+ exists = (driver->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
+
+ return exists ? attr->mode : 0;
+}
+
+static struct attribute_group toshiba_attr_group = {
+ .is_visible = toshiba_sysfs_is_visible,
+ .attrs = toshiba_attributes,
+};
+
static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@@ -1179,6 +1385,10 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
remove_toshiba_proc_entries(dev);
+ if (dev->sysfs_created)
+ sysfs_remove_group(&dev->pf_dev->dev.kobj,
+ &toshiba_attr_group);
+
if (dev->ntfy_supported) {
i8042_remove_filter(toshiba_acpi_i8042_filter);
cancel_work_sync(&dev->hotkey_work);
@@ -1200,6 +1410,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
if (dev->illumination_supported)
led_classdev_unregister(&dev->led_dev);
+ if (dev->kbd_led_registered)
+ led_classdev_unregister(&dev->kbd_led);
+
if (dev->pf_dev)
platform_device_unregister(dev->pf_dev);
@@ -1302,6 +1515,25 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->illumination_supported = 1;
}
+ ret = toshiba_kbd_illum_status_get(dev, &dummy);
+ if (!ret) {
+ dev->kbd_time = dummy >> HCI_MISC_SHIFT;
+ dev->kbd_mode = dummy & 0x07;
+ }
+ dev->kbd_illum_supported = !ret;
+ /*
+ * Only register the LED if KBD illumination is supported
+ * and the keyboard backlight operation mode is set to FN-Z
+ */
+ if (dev->kbd_illum_supported && dev->kbd_mode == SCI_KBD_MODE_FNZ) {
+ dev->kbd_led.name = "toshiba::kbd_backlight";
+ dev->kbd_led.max_brightness = 1;
+ dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
+ dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
+ if (!led_classdev_register(&dev->pf_dev->dev, &dev->kbd_led))
+ dev->kbd_led_registered = 1;
+ }
+
/* Determine whether or not BIOS supports fan and video interfaces */
ret = get_video_status(dev, &dummy);
@@ -1310,6 +1542,16 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
ret = get_fan_status(dev, &dummy);
dev->fan_supported = !ret;
+ ret = sysfs_create_group(&dev->pf_dev->dev.kobj,
+ &toshiba_attr_group);
+ if (ret) {
+ platform_device_del(dev->pf_dev);
+ platform_device_put(dev->pf_dev);
+ dev->sysfs_created = 0;
+ goto error;
+ }
+ dev->sysfs_created = !ret;
+
create_toshiba_proc_entries(dev);
toshiba_acpi = dev;
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/8] toshiba_acpi: Add ECO led support
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
` (3 preceding siblings ...)
2013-11-05 3:48 ` [PATCH 4/8] toshiba_acpi: Add kbd backlight support and sysfs files Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 6/8] toshiba_acpi: Add accelerometer support Azael Avalos
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Newer Toshiba laptops now come with a feature called
ECO Mode, where the system is put in low power consupmtion
state and a green (world shaped with leaves) icon illuminates
indicating that the system is in such power state.
This patch adds support to turn on/off the ECO led by
creating and registering the toshiba::eco_mode led.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 66 +++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index f97f942..022c6e6 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -113,6 +113,7 @@ MODULE_LICENSE("GPL");
#define HCI_LCD_BRIGHTNESS 0x002a
#define HCI_WIRELESS 0x0056
#define HCI_KBD_ILLUMINATION 0x0095
+#define HCI_ECO_MODE 0x0097
#define SCI_ILLUMINATION 0x014e
#define SCI_KBD_ILLUM_STATUS 0x015c
@@ -143,6 +144,7 @@ struct toshiba_acpi_dev {
struct backlight_device *backlight_dev;
struct led_classdev led_dev;
struct led_classdev kbd_led;
+ struct led_classdev eco_led;
int force_fan;
int last_key_event;
@@ -159,6 +161,7 @@ struct toshiba_acpi_dev {
unsigned int tr_backlight_supported:1;
unsigned int kbd_illum_supported:1;
unsigned int kbd_led_registered:1;
+ unsigned int eco_supported:1;
unsigned int sysfs_created:1;
struct mutex mutex;
@@ -538,6 +541,57 @@ static void toshiba_kbd_backlight_set(struct led_classdev *cdev,
}
}
+/* Eco Mode support */
+static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev)
+{
+ acpi_status status;
+ u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 };
+ u32 out[HCI_WORDS];
+
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == INPUT_DATA_ERROR) {
+ pr_info("ACPI call to get ECO led failed\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static enum led_brightness toshiba_eco_mode_get_status(struct led_classdev *cdev)
+{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, eco_led);
+ u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to get ECO led failed\n");
+ return LED_OFF;
+ }
+
+ return out[2] ? LED_FULL : LED_OFF;
+}
+
+static void toshiba_eco_mode_set_status(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct toshiba_acpi_dev *dev = container_of(cdev,
+ struct toshiba_acpi_dev, eco_led);
+ u32 in[HCI_WORDS] = { HCI_SET, HCI_ECO_MODE, 0, 1, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ /* Switch the Eco Mode led on/off */
+ in[2] = (brightness) ? 1 : 0;
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to set ECO led failed\n");
+ return;
+ }
+}
+
/* Bluetooth rfkill handlers */
static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1413,6 +1467,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
if (dev->kbd_led_registered)
led_classdev_unregister(&dev->kbd_led);
+ if (dev->eco_supported)
+ led_classdev_unregister(&dev->eco_led);
+
if (dev->pf_dev)
platform_device_unregister(dev->pf_dev);
@@ -1515,6 +1572,15 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->illumination_supported = 1;
}
+ if (toshiba_eco_mode_available(dev)) {
+ dev->eco_led.name = "toshiba::eco_mode";
+ dev->eco_led.max_brightness = 1;
+ dev->eco_led.brightness_set = toshiba_eco_mode_set_status;
+ dev->eco_led.brightness_get = toshiba_eco_mode_get_status;
+ if (!led_classdev_register(&dev->pf_dev->dev, &dev->eco_led))
+ dev->eco_supported = 1;
+ }
+
ret = toshiba_kbd_illum_status_get(dev, &dummy);
if (!ret) {
dev->kbd_time = dummy >> HCI_MISC_SHIFT;
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/8] toshiba_acpi: Add accelerometer support
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
` (4 preceding siblings ...)
2013-11-05 3:48 ` [PATCH 5/8] toshiba_acpi: Add ECO led support Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 7/8] toshiba_acpi: Add touchpad enable/disable support Azael Avalos
2013-11-05 3:48 ` [PATCH 8/8] toshiba_acpi: Update version and copyright information Azael Avalos
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Recent Toshiba laptops now come equiped with a built in
accelerometer (TOS620A), but such device does not
expose the axis information, however, HCI calls 0x006d
and 0x00a6 can be used to query such info.
This patch adds support to read the axis values and
exposing them through the _position_ sysfs file.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 79 +++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 022c6e6..9c718eb 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -103,6 +103,8 @@ MODULE_LICENSE("GPL");
#define INPUT_DATA_ERROR 0x8300
#define NOT_PRESENT 0x8600
#define FIFO_EMPTY 0x8c00
+#define DATA_NOT_AVAILABLE 0x8d20
+#define NOT_INITIALIZED 0x8d50
/* registers */
#define HCI_FAN 0x0004
@@ -112,12 +114,15 @@ MODULE_LICENSE("GPL");
#define HCI_HOTKEY_EVENT 0x001e
#define HCI_LCD_BRIGHTNESS 0x002a
#define HCI_WIRELESS 0x0056
+#define HCI_ACCELEROMETER 0x006d
#define HCI_KBD_ILLUMINATION 0x0095
#define HCI_ECO_MODE 0x0097
+#define HCI_ACCELEROMETER2 0x00a6
#define SCI_ILLUMINATION 0x014e
#define SCI_KBD_ILLUM_STATUS 0x015c
/* field definitions */
+#define HCI_ACCEL_MASK 0x7fff
#define HCI_HOTKEY_DISABLE 0x0b
#define HCI_HOTKEY_ENABLE 0x09
#define HCI_LCD_BRIGHTNESS_BITS 3
@@ -162,6 +167,7 @@ struct toshiba_acpi_dev {
unsigned int kbd_illum_supported:1;
unsigned int kbd_led_registered:1;
unsigned int eco_supported:1;
+ unsigned int accelerometer_supported:1;
unsigned int sysfs_created:1;
struct mutex mutex;
@@ -592,6 +598,51 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev,
}
}
+/* Accelerometer support */
+static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev)
+{
+ u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ /* Check if the accelerometer call exists,
+ * this call also serves as initialization
+ */
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to query the accelerometer failed\n");
+ return -EIO;
+ } else if (out[0] == DATA_NOT_AVAILABLE || out[0] == NOT_INITIALIZED) {
+ pr_err("Accelerometer not initialized\n");
+ return -EIO;
+ } else if (out[0] == NOT_SUPPORTED) {
+ pr_info("Accelerometer not supported\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
+ u32 *xy, u32 *z)
+{
+ u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status;
+
+ /* Check the Accelerometer status */
+ status = hci_raw(dev, in, out);
+ if (ACPI_FAILURE(status) || out[0] == INPUT_DATA_ERROR) {
+ pr_err("ACPI call to query the accelerometer failed\n");
+ return -EIO;
+ }
+
+ *xy = out[2];
+ *z = out[4];
+
+ return 0;
+}
+
/* Bluetooth rfkill handlers */
static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1195,14 +1246,37 @@ static ssize_t toshiba_kbd_bl_timeout_show(struct device *dev,
return sprintf(buf, "%i\n", time >> HCI_MISC_SHIFT);
}
+static ssize_t toshiba_position_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ u32 xyval, zval, tmp;
+ u16 x, y, z;
+ int ret;
+
+ xyval = zval = 0;
+ ret = toshiba_accelerometer_get(toshiba, &xyval, &zval);
+ if (ret < 0)
+ return ret;
+
+ x = xyval & HCI_ACCEL_MASK;
+ tmp = xyval >> HCI_MISC_SHIFT;
+ y = tmp & HCI_ACCEL_MASK;
+ z = zval & HCI_ACCEL_MASK;
+
+ return sprintf(buf, "%d %d %d\n", x, y, z);
+}
+
static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store);
+static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
static struct attribute *toshiba_attributes[] = {
&dev_attr_kbd_backlight_mode.attr,
&dev_attr_kbd_backlight_timeout.attr,
+ &dev_attr_position.attr,
NULL,
};
@@ -1218,6 +1292,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
exists = (driver->kbd_illum_supported) ? true : false;
else if (attr == &dev_attr_kbd_backlight_timeout.attr)
exists = (driver->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
+ else if (attr == &dev_attr_position.attr)
+ exists = (driver->accelerometer_supported) ? true : false;
return exists ? attr->mode : 0;
}
@@ -1600,6 +1676,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
dev->kbd_led_registered = 1;
}
+ ret = toshiba_accelerometer_supported(dev);
+ dev->accelerometer_supported = !ret;
+
/* Determine whether or not BIOS supports fan and video interfaces */
ret = get_video_status(dev, &dummy);
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/8] toshiba_acpi: Add touchpad enable/disable support
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
` (5 preceding siblings ...)
2013-11-05 3:48 ` [PATCH 6/8] toshiba_acpi: Add accelerometer support Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
2013-11-05 3:48 ` [PATCH 8/8] toshiba_acpi: Update version and copyright information Azael Avalos
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Toshiba laptops have two ways of enabling/disabling the
touchpad, one with a hardwired button on top of the touchpad
that simply emmits scancodes to let userspace know it has changed,
and another with a SCI call that triggers (on Windows drivers)
whenever the user press the Fn-F9 (touchpad toggle) hotkey.
This patch adds support to enable/disable the touchpad
by exposing the _touchpad_ file in sysfs.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 81 +++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 9c718eb..0e14e9c 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -120,6 +120,7 @@ MODULE_LICENSE("GPL");
#define HCI_ACCELEROMETER2 0x00a6
#define SCI_ILLUMINATION 0x014e
#define SCI_KBD_ILLUM_STATUS 0x015c
+#define SCI_TOUCHPAD 0x050e
/* field definitions */
#define HCI_ACCEL_MASK 0x7fff
@@ -168,6 +169,7 @@ struct toshiba_acpi_dev {
unsigned int kbd_led_registered:1;
unsigned int eco_supported:1;
unsigned int accelerometer_supported:1;
+ unsigned int touchpad_supported:1;
unsigned int sysfs_created:1;
struct mutex mutex;
@@ -643,6 +645,47 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
return 0;
}
+/* TouchPad support */
+static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state)
+{
+ u32 result;
+ acpi_status status;
+
+ if (!sci_open(dev))
+ return -EIO;
+
+ status = sci_write(dev, SCI_TOUCHPAD, state, &result);
+ sci_close(dev);
+ if (ACPI_FAILURE(status)) {
+ pr_err("ACPI call to set the touchpad failed\n");
+ return -EIO;
+ } else if (result == NOT_SUPPORTED) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state)
+{
+ u32 result;
+ acpi_status status;
+
+ if (!sci_open(dev))
+ return -EIO;
+
+ status = sci_read(dev, SCI_TOUCHPAD, state, &result);
+ sci_close(dev);
+ if (ACPI_FAILURE(status)) {
+ pr_err("ACPI call to query the touchpad failed\n");
+ return -EIO;
+ } else if (result == NOT_SUPPORTED) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
/* Bluetooth rfkill handlers */
static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1267,16 +1310,49 @@ static ssize_t toshiba_position_show(struct device *dev,
return sprintf(buf, "%d %d %d\n", x, y, z);
}
+static ssize_t toshiba_touchpad_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ int state;
+
+ /* Set the TouchPad on/off, 0 - Disable | 1 - Enable */
+ if (sscanf(buf, "%i", &state) == 1 && (state == 0 || state == 1)) {
+ if (toshiba_touchpad_set(toshiba, state) < 0)
+ return -EIO;
+ }
+
+ return count;
+}
+
+static ssize_t toshiba_touchpad_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
+ u32 state;
+ int ret;
+
+ ret = toshiba_touchpad_get(toshiba, &state);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%i\n", state);
+}
+
static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store);
static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
+static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR,
+ toshiba_touchpad_show, toshiba_touchpad_store);
static struct attribute *toshiba_attributes[] = {
&dev_attr_kbd_backlight_mode.attr,
&dev_attr_kbd_backlight_timeout.attr,
&dev_attr_position.attr,
+ &dev_attr_touchpad.attr,
NULL,
};
@@ -1294,6 +1370,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
exists = (driver->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
else if (attr == &dev_attr_position.attr)
exists = (driver->accelerometer_supported) ? true : false;
+ else if (attr == &dev_attr_touchpad.attr)
+ exists = (driver->touchpad_supported) ? true : false;
return exists ? attr->mode : 0;
}
@@ -1679,6 +1757,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
ret = toshiba_accelerometer_supported(dev);
dev->accelerometer_supported = !ret;
+ ret = toshiba_touchpad_get(dev, &dummy);
+ dev->touchpad_supported = !ret;
+
/* Determine whether or not BIOS supports fan and video interfaces */
ret = get_video_status(dev, &dummy);
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 8/8] toshiba_acpi: Update version and copyright information
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
` (6 preceding siblings ...)
2013-11-05 3:48 ` [PATCH 7/8] toshiba_acpi: Add touchpad enable/disable support Azael Avalos
@ 2013-11-05 3:48 ` Azael Avalos
7 siblings, 0 replies; 9+ messages in thread
From: Azael Avalos @ 2013-11-05 3:48 UTC (permalink / raw)
To: Matthew Garrett, linux-kernel; +Cc: azael.avalos
Add myself to the copyright list and bump version to
0.20 since several new features have been added.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
---
drivers/platform/x86/toshiba_acpi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 0e14e9c..22178f2 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -5,6 +5,7 @@
* Copyright (C) 2002-2004 John Belmonte
* Copyright (C) 2008 Philip Langdale
* Copyright (C) 2010 Pierre Ducroquet
+ * Copyright (C) 2013 Azael Avalos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,7 +38,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#define TOSHIBA_ACPI_VERSION "0.19"
+#define TOSHIBA_ACPI_VERSION "0.20"
#define PROC_INTERFACE_VERSION 1
#include <linux/kernel.h>
--
1.8.1.4
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2013-11-05 3:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-05 3:48 [PATCH 0/8] toshiba_acpi: New features added and a fix Azael Avalos
2013-11-05 3:48 ` [PATCH 1/8] toshiba_acpi: Add System Configuration Interface (SCI) Azael Avalos
2013-11-05 3:48 ` [PATCH 2/8] toshiba_acpi: Adapt illumination_* code to use the new SCI Azael Avalos
2013-11-05 3:48 ` [PATCH 3/8] toshiba_acpi: Add platform support Azael Avalos
2013-11-05 3:48 ` [PATCH 4/8] toshiba_acpi: Add kbd backlight support and sysfs files Azael Avalos
2013-11-05 3:48 ` [PATCH 5/8] toshiba_acpi: Add ECO led support Azael Avalos
2013-11-05 3:48 ` [PATCH 6/8] toshiba_acpi: Add accelerometer support Azael Avalos
2013-11-05 3:48 ` [PATCH 7/8] toshiba_acpi: Add touchpad enable/disable support Azael Avalos
2013-11-05 3:48 ` [PATCH 8/8] toshiba_acpi: Update version and copyright information Azael Avalos
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®