OBJS = init.o lib.o ec.o kbc.o pio.o compal.o acpi.o nbsmi.o \
- ac.o battery.o blank.o bluetooth.o display.o dock.o dump.o \
- fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o polling.o \
- temperature.o touchpad.o wireless.o
+ ac.o battery.o blank.o bluetooth.o cooling.o display.o dock.o \
+ dump.o fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o \
+ polling.o temperature.o touchpad.o wireless.o throttling.o
obj-m += $(MODULE_NAME).o
omnibook-objs := $(OBJS)
#define CRT_CSTE 0x2
#define TVO_CSTE 0x4
+#define GET_THROTTLE_METHOD "THRO"
+#define SET_THROTTLE_METHOD "CLCK"
+
static char ec_dev_list[][20] = {
"\\_SB.PCI0.LPCB.EC0",
"\\_SB.PCI0.LPC0.EC0",
#define TOSHIBA_ACPI_BT_CLASS "bluetooth"
#define TOSHIBA_ACPI_DEVICE_NAME "bluetooth adapter"
-#define TOSH_BT_ACTIVATE_USB "AUSB"
-#define TOSH_BT_DISABLE_USB "DUSB"
-#define TOSH_BT_POWER_ON "BTPO"
-#define TOSH_BT_POWER_OFF "BTPF"
-#define TOSH_BT_STATUS "BTST"
+#define TOSH_BT_ACTIVATE_USB "AUSB"
+#define TOSH_BT_DISABLE_USB "DUSB"
+#define TOSH_BT_POWER_ON "BTPO"
+#define TOSH_BT_POWER_OFF "BTPF"
+#define TOSH_BT_STATUS "BTST"
#define TOSH_BT_KSST_MASK 0x1
#define TOSH_BT_USB_MASK 0x40
#define TOSH_BT_POWER_MASK 0x80
/*
* Execute an ACPI method which return either an integer or nothing
+ * and that require 0 or 1 numerical argument
* (acpi_evaluate_object wrapper)
*/
static int omnibook_acpi_execute(acpi_handle dev_handle, char *method, const int *param, int *result)
dprintk("Enabling found Toshiba Bluetooth ACPI device.\n");
strcpy(acpi_device_name(device), TOSHIBA_ACPI_DEVICE_NAME);
- strcpy(acpi_device_class(device), TOSHIBA_ACPI_BT_CLASS);
+ strcpy(acpi_device_class(device), TOSHIBA_ACPI_BT_CLASS);
/* Save handle in backend private data structure. ugly. */
priv_data->bt_handle = device->handle;
int retval = 0;
int raw_state;
- if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, 0, &raw_state)))
+ if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state)))
return retval;
dprintk("BTST raw_state: %x\n", raw_state);
int retval = 0;
int raw_state;
- if ((retval = omnibook_acpi_execute(priv_data->ec_handle, GET_WIRELESS_METHOD, 0, &raw_state)))
+ if ((retval = omnibook_acpi_execute(priv_data->ec_handle, GET_WIRELESS_METHOD, NULL, &raw_state)))
return retval;
dprintk("get_wireless raw_state: %x\n", raw_state);
int raw_state = 0;
struct acpi_backend_data *priv_data = io_op->backend->data;
- retval = omnibook_acpi_execute(priv_data->ec_handle, GET_DISPLAY_METHOD, 0, &raw_state);
+ retval = omnibook_acpi_execute(priv_data->ec_handle, GET_DISPLAY_METHOD, NULL, &raw_state);
if (retval < 0)
return retval;
return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON;
}
+static int omnibook_acpi_get_throttle(const struct omnibook_operation *io_op, unsigned int *state)
+{
+ int retval;
+ int thtl_en = 0, thtl_dty = 0;
+ int param;
+ struct acpi_backend_data *priv_data = io_op->backend->data;
+
+ param = 0;
+ /* Read THEN aka THTL_EN in ICH6M datasheets */
+ retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, ¶m, &thtl_en);
+ if ( thtl_en == 0 ) {
+ *state = 0;
+ return retval;
+ }
+ param = 1;
+ /* Read DUTY aka THTL_DTY in ICH6M datasheets */
+ retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, ¶m, &thtl_dty);
+ WARN_ON(thtl_dty > 7); /* We shouldn't encounter more than 7 throttling level */
+ *state = 8 - thtl_dty; /* THTL_DTY and ACPI T-state are reverse mapped */
+ return retval;
+}
+
+static int omnibook_acpi_set_throttle(const struct omnibook_operation *io_op, unsigned int state)
+{
+ struct acpi_backend_data *priv_data = io_op->backend->data;
+ /* THTL_DTY and ACPI T-state are reverse mapped */
+ /* throttling.c already clamped state between 0 and 7 */
+ if (state)
+ state = 8 - state;
+
+ return omnibook_acpi_execute(priv_data->ec_handle, SET_THROTTLE_METHOD, &state, NULL);
+}
+
+
struct omnibook_backend acpi_backend = {
.name = "acpi",
.init = omnibook_acpi_init,
.aerial_set = omnibook_acpi_set_wireless,
.display_get = omnibook_acpi_get_display,
.display_set = omnibook_acpi_set_display,
+ .throttle_get = omnibook_acpi_get_throttle,
+ .throttle_set = omnibook_acpi_set_throttle,
};
#else /* CONFIG_ACPI */
--- /dev/null
+/*
+ * colling.c -- cooling methods feature
+ *
+ * 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 the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2007
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_cooling_read(char *buffer, struct omnibook_operation *io_op)
+{
+ int len = 0;
+
+ if(mutex_lock_interruptible(&io_op->backend->mutex))
+ return -ERESTARTSYS;
+
+ len += sprintf(buffer + len, "Cooling method : %s\n",
+ io_op->backend->cooling_state ? "Performance" : "Powersave" );
+
+ mutex_unlock(&io_op->backend->mutex);
+ return len;
+}
+
+static int omnibook_cooling_write(char *buffer, struct omnibook_operation *io_op)
+{
+ int retval = 0;
+
+ if (*buffer == '0') {
+ retval = backend_byte_write(io_op,
+ TSM70_COOLING_OFFSET + TSM70_COOLING_POWERSAVE);
+ } else if (*buffer == '1') {
+ retval = backend_byte_write(io_op,
+ TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+ } else {
+ return -EINVAL;
+ }
+
+ return retval;
+}
+
+static int __init omnibook_cooling_init(struct omnibook_operation *io_op)
+{
+ mutex_lock(&io_op->backend->mutex);
+ /* XXX: Assumed default cooling method: performance */
+ io_op->backend->cooling_state = TSM70_COOLING_PERF;
+ mutex_unlock(&io_op->backend->mutex);
+ return 0;
+}
+
+static void __exit omnibook_cooling_exit(struct omnibook_operation *io_op)
+{
+ /* Set back cooling method to performance */
+ backend_byte_write(io_op, TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+}
+
+static struct omnibook_tbl cooling_table[] __initdata = {
+ {TSM70, {CDI, 0, TSM70_FN_INDEX, 0, 0, 0 }},
+ {0,}
+};
+
+struct omnibook_feature __declared_feature cooling_driver = {
+ .name = "cooling",
+ .enabled = 1,
+ .read = omnibook_cooling_read,
+ .write = omnibook_cooling_write,
+ .init = omnibook_cooling_init,
+ .exit = omnibook_cooling_exit,
+ .ectypes = TSM70,
+ .tbl = cooling_table,
+};
+
+module_param_named(cooling, cooling_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(cooling, "Use 0 to disable, 1 to enable CPU cooling method control");
+
+/* End of file */
The state of the Toshiba M35X is unknown and is assigned to TSM70, one
should send a bug report if that fail.
Fix bugs 1617818 and 1605278
+* New features for TSM70 class laptops:
+ -Cooling method control (can tune fan behaviour to 'Save power' or
+ to 'Maximize performance') provided in /proc/omnibook/cooling
+ -CPU Throttling status&control (also known as ACPI T-States) should
+ be supported out of the box via /proc/acpi/processor/CPU0/throttling
+ but at least Toshiba Satellite M70 as a deficient ACPI FADT table
+ which prevent than, thus a custom access to ACPI Throttling is
+ provided in /proc/omnibook/throttling
2.20060921 Mathieu Bérard <math_b@users.sourceforge.net>
* The minimal required kernel version is now 2.6.9 (kref API)
sprintf(buffer + len,
"EC " " +00 +01 +02 +03 +04 +05 +06 +07"
" +08 +09 +0a +0b +0c +0d +0e +0f\n");
+
+ if(mutex_lock_interruptible(&io_op->backend->mutex))
+ return -ERESTARTSYS;
+
for (i = 0; i < 255; i += 16) {
len += sprintf(buffer + len, "EC 0x%02x:", i);
for (j = 0; j < 16; j++) {
io_op->read_addr = i +j;
- if (backend_byte_read(io_op, &v))
+ if (__backend_byte_read(io_op, &v))
break;
if (v != ecdump_regs[i + j])
len += sprintf(buffer + len, " *%02x", v);
break;
}
+ mutex_unlock(&io_op->backend->mutex);
+
/* These are way too dangerous to advertise openly... */
#if 0
len +=
* General Public License for more details.
*
* Written by Soós Péter <sp@osb.hu>, 2002-2004
- * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
*/
#include <linux/acpi.h>
/* Public data fields, access with mutex held */
unsigned int hotkeys_state; /* saved hotkeys state */
- unsigned int misc_state; /* various status bit: touchpad and muteled */
+ unsigned int touchpad_state; /* saved touchpad state */
+ unsigned int muteled_state; /* saved muteled state */
+ unsigned int cooling_state; /* saved cooling method state */
/* Public function pointers */
int (*init) (const struct omnibook_operation *);
int (*hotkeys_set) (const struct omnibook_operation *, unsigned int);
int (*display_get) (const struct omnibook_operation *, unsigned int *);
int (*display_set) (const struct omnibook_operation *, unsigned int);
+ int (*throttle_get) (const struct omnibook_operation *, unsigned int *);
+ int (*throttle_set) (const struct omnibook_operation *, unsigned int);
/* Private fields, never to be accessed outside backend code */
struct kref kref; /* Reference counter of this backend */
helper_func(aerial)
helper_func(hotkeys)
helper_func(display)
+helper_func(throttle)
static inline int backend_byte_read(const struct omnibook_operation *io_op, u8 *data)
{
#define TSM100_BLANK_INDEX 0x59
#define TSM100_LCD_ON 0xe1
#define TSM100_LCD_OFF 0xe2
+#define TSM70_COOLING_OFFSET 0xb0
+#define TSM70_COOLING_POWERSAVE 0x0
+#define TSM70_COOLING_PERF 0x2
/* Toshiba SMI funtions and constants*/
#define SMI_FN_PRESSED 0x8f
goto out;
}
- io_op->backend->misc_state =
- (io_op->backend->misc_state & ~MUTELED) | (MUTELED * !!status);
+ io_op->backend->muteled_state = !!status;
out:
mutex_unlock(&io_op->backend->mutex);
return -ERESTARTSYS;
len +=
sprintf(buffer + len, "Last mute LED action was an %s command.\n",
- (io_op->backend->misc_state & MUTELED) ? "on" : "off");
+ io_op->backend->touchpad_state ? "on" : "off");
mutex_unlock(&io_op->backend->mutex);
return len;
{
int retval;
mutex_lock(&io_op->backend->mutex);
- retval = __omnibook_toggle(io_op, !!(io_op->backend->misc_state & MUTELED));
+ retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state);
mutex_unlock(&io_op->backend->mutex);
return retval;
}
#define HKEY_LAST_SHIFT 6
-/*
- * Various status bits
- */
-enum {
- MUTELED = (1<<0), /* Mute LED status */
- TOUCHPAD = (1<<1), /* Touchpad status */
-};
-
-
/*
* Display state backend neutral masks
* _ON masks = port is powered up and running
if (match)
kref_put(&match->refcount, omnibook_free_port);
- match = NULL;
match = omnibook_match_port(io_op->backend->data, io_op->write_addr);
if (match)
kref_put(&match->refcount, omnibook_free_port);
--- /dev/null
+/*
+ * throttling.c --CPU throttling control feature
+ *
+ * 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 the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2007
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+/*
+ * Throttling level/rate mapping found in ICH6M datasheets
+ * the output is set to mimic the one of /proc/acpi/cpu/CPU0/throttling
+ * XXX: We always assume that there are 8 T-States and one processor.
+ */
+static const int trate[8] = { 0, 12, 25, 37, 50, 62, 75, 87 };
+
+static int omnibook_throttle_read(char *buffer, struct omnibook_operation *io_op)
+{
+ int len = 0;
+ int tstate = 0;
+ int retval, i;
+
+ retval = backend_throttle_get(io_op, &tstate);
+ if (retval < 0)
+ return retval;
+
+ len += sprintf(buffer + len, "state count: 8\n");
+ len += sprintf(buffer + len, "active state: T%d\n", tstate);
+ for (i = 0; i < 8; i += 1)
+ {
+ len += sprintf(buffer + len, " %cT%d: %02d%%\n",
+ (i == tstate ? '*' : ' '),
+ i,
+ trate[i]);
+ }
+
+ return len;
+}
+
+static int omnibook_throttle_write(char *buffer, struct omnibook_operation *io_op)
+{
+ int retval = 0;
+ int data;
+ char *endp;
+
+ data = simple_strtoul(buffer, &endp, 10);
+ if ((endp == buffer) || (data > 7)) /* There are 8 throttling levels */
+ return -EINVAL;
+ else
+ retval = backend_throttle_set(io_op, data);
+
+ return retval;
+}
+
+
+static struct omnibook_tbl throttle_table[] __initdata = {
+ {TSM70, {ACPI,}},
+ {0,}
+};
+
+struct omnibook_feature __declared_feature throttle_driver = {
+ .name = "throttling",
+ .enabled = 1,
+ .read = omnibook_throttle_read,
+ .write = omnibook_throttle_write,
+ .ectypes = TSM70,
+ .tbl = throttle_table,
+};
+
+module_param_named(throttle, throttle_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(throttle, "Use 0 to disable, 1 to enable CPU throttling control");
+
+/* End of file */
goto out;
}
- io_op->backend->misc_state =
- (io_op->backend->misc_state & ~TOUCHPAD) | (TOUCHPAD * !!status);
+ io_op->backend->touchpad_state = !!status;
out:
mutex_unlock(&io_op->backend->mutex);
{
int retval;
mutex_lock(&io_op->backend->mutex);
- retval = __omnibook_toggle(io_op, !!(io_op->backend->misc_state & TOUCHPAD));
+ retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state);
mutex_unlock(&io_op->backend->mutex);
return retval;
}
len +=
sprintf(buffer + len, "Last touchpad action was an %s command.\n",
- (io_op->backend->misc_state & TOUCHPAD) ? "enable" : "disable");
+ io_op->backend->touchpad_state ? "enable" : "disable");
mutex_unlock(&io_op->backend->mutex);
return len;
{
mutex_lock(&io_op->backend->mutex);
/* Touchpad is assumed to be enabled by default */
- io_op->backend->misc_state |= TOUCHPAD;
+ io_op->backend->touchpad_state = 1;
mutex_unlock(&io_op->backend->mutex);
return 0;
}