* [PATCH] ACPI: add "Fujitsu laptop extras" module
@ 2007-08-24 0:42 Jonathan Woithe
2007-08-24 1:32 ` Matthew Garrett
0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-24 0:42 UTC (permalink / raw)
To: linux-acpi; +Cc: Jonathan Woithe
The following patch adds support for features on various Fujitsu laptops
which are not accessible using the "standard" ACPI kernel modules. Of
particular interest to me is the software control of screen brightness,
which allows software to turn the screen back on following a resume from
suspend-to-ram.
This patch was originally created by "hardwire" on the "Fujitsu P Series
Forum" at http://leog.net/fujp%5Fforum/topic.asp?ARCHIVE=true&TOPIC_ID=3388.
Adrian Yee (brewt-fujitsu@brewt.org) "cleaned up the code and made some
fixes". I have simply re-based the patch against 2.6.22.3 and added mention
of the S7xxx to the Kconfig help text.
While originally written for the P-series laptops I can confirm that the LCD
brightness control (which is the only thing I really care about) also
functions correctly on my S7020, so it seems it's fine for the S-series as
well.
Please apply, or tell me what needs to be done to make this acceptable.
Regards
jonathan
diff -ruN linux-2.6.22.3-orig/drivers/acpi/Kconfig linux-2.6.22.3/drivers/acpi/Kconfig
--- linux-2.6.22.3-orig/drivers/acpi/Kconfig 2007-08-16 01:55:39.000000000 +0930
+++ linux-2.6.22.3/drivers/acpi/Kconfig 2007-08-24 09:30:11.000000000 +0930
@@ -245,6 +245,16 @@
If you have a legacy free Toshiba laptop (such as the Libretto L1
series), say Y.
+config ACPI_FUJ02B1
+ tristate "Fujitsu FUJ02B1 Laptop Extras"
+ depends on X86 && ACPI && !ACPI_HT_ONLY
+ help
+ This driver adds support for access to certain system settings
+ on Fujitsu laptops.
+
+ If you have a Fujitsu laptop (such as the P2xxx/P5xxx/S6xxx/S7xxx
+ series), say Y.
+
config ACPI_CUSTOM_DSDT
bool "Include Custom DSDT"
depends on !STANDALONE
diff -ruN linux-2.6.22.3-orig/drivers/acpi/Makefile linux-2.6.22.3/drivers/acpi/Makefile
--- linux-2.6.22.3-orig/drivers/acpi/Makefile 2007-08-16 01:55:39.000000000 +0930
+++ linux-2.6.22.3/drivers/acpi/Makefile 2007-08-24 09:27:36.000000000 +0930
@@ -57,6 +57,7 @@
obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
+obj-$(CONFIG_ACPI_FUJ02B1) += fuj02b1_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
diff -ruN linux-2.6.22.3-orig/drivers/acpi/fuj02b1_acpi.c linux-2.6.22.3/drivers/acpi/fuj02b1_acpi.c
--- linux-2.6.22.3-orig/drivers/acpi/fuj02b1_acpi.c 1970-01-01 09:30:00.000000000 +0930
+++ linux-2.6.22.3/drivers/acpi/fuj02b1_acpi.c 2007-08-24 09:25:55.000000000 +0930
@@ -0,0 +1,612 @@
+/*
+ * fuj02b1.c - Fujitsu FUJ02B1 ACPI Extras
+ *
+ * Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
+ *
+ * Templated from on fan.c
+ *
+ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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 of the License, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ * clean notify output and define a standard.. based on acpi events from the toshiba code
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define ACPI_FUJ02B1_CLASS "fuj02b1"
+#define ACPI_FUJ02B1_HID "FUJ02B1"
+#define ACPI_FUJ02B1_DRIVER_NAME "Fujitsu FUJ02B1 ACPI Extras Driver"
+#define ACPI_FUJ02B1_DEVICE_NAME "FUJ02B1"
+#define ACPI_FUJ02B1_FILE_POINTER "pointer"
+#define ACPI_FUJ02B1_FILE_VOLUME "volume"
+#define ACPI_FUJ02B1_FILE_BRIGHTNESS "brightness"
+#define ACPI_FUJ02B1_NOTIFY_STATUS 0x80
+
+#define PREFIX "ACPI: "
+#define ACPI_FUJ02B1_COMPONENT 0x00200000
+#define _COMPONENT ACPI_FUJ02B1_COMPONENT
+ACPI_MODULE_NAME("acpi_fuj02b1");
+
+MODULE_AUTHOR("Shane Spencer");
+MODULE_DESCRIPTION(ACPI_FUJ02B1_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+int acpi_fuj02b1_add(struct acpi_device *device);
+int acpi_fuj02b1_remove(struct acpi_device *device, int type);
+
+/* an sscanf that takes explicit string length **STOLEN FROM TOSHIBA_ACPI.C** */
+static int snscanf(const char* str, int n, const char* format, ...)
+{
+ va_list args;
+ int result;
+ char* str2 = kmalloc(n + 1, GFP_KERNEL);
+ if (str2 == 0) return 0;
+ /* NOTE: don't even _think_ about replacing this with strlcpy */
+ strncpy(str2, str, n);
+ str2[n] = 0;
+ va_start(args, format);
+ result = vsscanf(str2, format, args);
+ va_end(args);
+ kfree(str2);
+ return result;
+}
+
+static struct acpi_driver acpi_fuj02b1_driver = {
+ .name = ACPI_FUJ02B1_DRIVER_NAME,
+ .class = ACPI_FUJ02B1_CLASS,
+ .ids = ACPI_FUJ02B1_HID,
+ .ops = {
+ .add = acpi_fuj02b1_add,
+ .remove = acpi_fuj02b1_remove,
+ },
+};
+
+struct acpi_fuj02b1 {
+ acpi_handle handle;
+ unsigned long state;
+ unsigned int mute_state;
+ unsigned int volume_level;
+ unsigned int volume_changed;
+ unsigned int brightness_level;
+ unsigned int brightness_changed;
+ unsigned int pointer_state;
+ unsigned int pointer_changed;
+};
+
+
+/* --------------------------------------------------------------------------
+ FS Interface (/proc)
+ -------------------------------------------------------------------------- */
+
+struct proc_dir_entry *acpi_fuj02b1_dir = NULL;
+
+
+/* --------------------------------------------------------------------------
+ Volume States
+ -------------------------------------------------------------------------- */
+
+static int acpi_fuj02b1_get_volume_state(void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ unsigned long state = 0;
+ acpi_status status = AE_OK;
+
+ // Get the Volume
+ status = acpi_evaluate_integer(fuj02b1->handle, "GVOL", NULL, &state);
+ fuj02b1->state = state;
+
+ fuj02b1->volume_level = state & 0x0fffffff;
+
+ if (state & 0x40000000)
+ fuj02b1->mute_state = 0;
+ else
+ fuj02b1->mute_state = 1;
+
+ if (state & 0x80000000)
+ fuj02b1->volume_changed = 1;
+ else
+ fuj02b1->volume_changed = 0;
+
+ return -1;
+}
+
+static int acpi_fuj02b1_read_volume_state(char *page, char **start,
+ off_t off, int count, int *eof, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char *p = page;
+ int len = 0;
+
+ if (!fuj02b1 || (off != 0))
+ goto end;
+
+ acpi_fuj02b1_get_volume_state(fuj02b1);
+
+ p += sprintf(p, "volume: %d\n", fuj02b1->volume_level);
+ p += sprintf(p, "mute: %s\n", !fuj02b1->mute_state ? "on" : "off");
+ p += sprintf(p, "volume levels: 16\n");
+
+end:
+ len = (p - page);
+ if (len <= off + count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+ return len;
+}
+
+static int acpi_fuj02b1_write_volume_state(struct file *file,
+ const char *buffer, unsigned long count, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char state_string[12] = {'\0'};
+ int volume;
+ int mute;
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = {ACPI_TYPE_INTEGER};
+ struct acpi_object_list arg_list = {1, &arg0};
+ acpi_handle handle = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_write_volume_state");
+
+ if (!fuj02b1 || (count > sizeof(state_string) - 1))
+ return -EINVAL;
+
+ if (copy_from_user(state_string, buffer, count))
+ return -EFAULT;
+
+ state_string[count] = '\0';
+
+ status = acpi_get_handle(fuj02b1->handle, "SVOL", &handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SVOL not present\n"));
+ return -ENODEV;
+ }
+
+ if (snscanf(buffer, count, " volume : %i", &volume) == 1 && volume >= 0 && volume <= 15) {
+ /* A change of volume results in unmute */
+ arg0.integer.value = volume;
+ } else if (snscanf(buffer, count, " mute : %i", &mute) == 1 && (mute == 0 || mute == 1)) {
+ /* Remember the volume level on a mute/unmute */
+ if (mute)
+ mute = 0x40000000 | fuj02b1->volume_level;
+ else
+ mute = fuj02b1->volume_level;
+ arg0.integer.value = mute;
+ } else
+ return -EINVAL;
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return count;
+}
+
+
+/* --------------------------------------------------------------------------
+ Brightness States
+ -------------------------------------------------------------------------- */
+
+static int acpi_fuj02b1_get_brightness_state(void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ unsigned long state = 0;
+ acpi_status status = AE_OK;
+
+ // Get the Brightness
+ status = acpi_evaluate_integer(fuj02b1->handle, "GBLL", NULL, &state);
+ fuj02b1->state = state;
+
+ fuj02b1->brightness_level = state & 0x0fffffff;
+
+ if (state & 0x80000000)
+ fuj02b1->brightness_changed = 1;
+ else
+ fuj02b1->brightness_changed = 0;
+
+ return -1;
+}
+
+static int acpi_fuj02b1_read_brightness_state(char *page, char **start,
+ off_t off, int count, int *eof, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char *p = page;
+ int len = 0;
+
+ if (!fuj02b1 || (off != 0))
+ goto end;
+
+ acpi_fuj02b1_get_brightness_state(fuj02b1);
+
+ p += sprintf(p, "brightness: %d\n", fuj02b1->brightness_level);
+ p += sprintf(p, "brightness levels: 8\n");
+
+end:
+ len = (p - page);
+ if (len <= off + count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+ return len;
+}
+
+static int acpi_fuj02b1_write_brightness_state(struct file *file,
+ const char *buffer, unsigned long count, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char state_string[24] = {'\0'};
+ int brightness;
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = {ACPI_TYPE_INTEGER};
+ struct acpi_object_list arg_list = {1, &arg0};
+ acpi_handle handle = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_write_brightness_state");
+
+ if (!fuj02b1 || (count > sizeof(state_string) - 1))
+ return -EINVAL;
+
+ if (copy_from_user(state_string, buffer, count))
+ return -EFAULT;
+
+ state_string[count] = '\0';
+
+ status = acpi_get_handle(fuj02b1->handle, "SBLL", &handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
+ return -ENODEV;
+ }
+
+ if (snscanf(buffer, count, " brightness : %i", &brightness) == 1 && brightness >= 0 && brightness <= 7)
+ arg0.integer.value = brightness;
+ else
+ {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No Woot \n"));
+ return -EINVAL;
+ }
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return count;
+}
+
+
+/* --------------------------------------------------------------------------
+ Pointer States
+ -------------------------------------------------------------------------- */
+
+static int acpi_fuj02b1_get_pointer_state(void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ unsigned long state = 0;
+ acpi_status status = AE_OK;
+
+ // Get the pointer state
+ status = acpi_evaluate_integer(fuj02b1->handle, "GMOU", NULL, &state);
+ fuj02b1->state = state;
+
+ fuj02b1->pointer_state = state & 0x0fffffff;
+
+ if (state & 0x80000000)
+ fuj02b1->pointer_changed = 1;
+ else
+ fuj02b1->pointer_changed = 0;
+
+ return -1;
+}
+
+static int acpi_fuj02b1_read_pointer_state(char *page, char **start,
+ off_t off, int count, int *eof, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char *p = page;
+ int len = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_read_pointer_state");
+
+ if (!fuj02b1 || (off != 0))
+ goto end;
+
+ acpi_fuj02b1_get_pointer_state(fuj02b1);
+
+ p += sprintf(p, "pointer: %d\n", fuj02b1->pointer_state);
+
+end:
+ len = (p - page);
+ if (len <= off + count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
+
+ return len;
+}
+
+static int acpi_fuj02b1_write_pointer_state(struct file *file,
+ const char *buffer, unsigned long count, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ char state_string[24] = {'\0'};
+ int pointer;
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = {ACPI_TYPE_INTEGER};
+ struct acpi_object_list arg_list = {1, &arg0};
+ acpi_handle handle = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_write_pointer_state");
+
+ if (!fuj02b1 || (count > sizeof(state_string) - 1))
+ return -EINVAL;
+
+ if (copy_from_user(state_string, buffer, count))
+ return -EFAULT;
+
+ state_string[count] = '\0';
+
+ status = acpi_get_handle(fuj02b1->handle, "SMOU", &handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMOU not present\n"));
+ return -ENODEV;
+ }
+
+ if (snscanf(buffer, count, " pointer : %i", &pointer) == 1 && (pointer == 0 || pointer == 1))
+ arg0.integer.value = pointer;
+ else
+ return -EINVAL;
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return count;
+}
+
+static int acpi_fuj02b1_add_fs(struct acpi_device *device)
+{
+ struct proc_dir_entry *entry_volume = NULL;
+ struct proc_dir_entry *entry_brightness = NULL;
+ struct proc_dir_entry *entry_pointer = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_add_fs");
+
+ if (!device)
+ return -EINVAL;
+
+ acpi_device_dir(device) = acpi_fuj02b1_dir;
+ if (!acpi_device_dir(device))
+ return -ENODEV;
+
+ /* 'status' [R/W] */
+ entry_volume = create_proc_entry(ACPI_FUJ02B1_FILE_VOLUME,
+ S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry_brightness = create_proc_entry(ACPI_FUJ02B1_FILE_BRIGHTNESS,
+ S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ entry_pointer = create_proc_entry(ACPI_FUJ02B1_FILE_POINTER,
+ S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+
+ if (!entry_volume)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_FUJ02B1_FILE_VOLUME));
+ else {
+ entry_volume->read_proc = acpi_fuj02b1_read_volume_state;
+ entry_volume->write_proc = acpi_fuj02b1_write_volume_state;
+ entry_volume->data = acpi_driver_data(device);
+ }
+
+ if (!entry_brightness)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_FUJ02B1_FILE_BRIGHTNESS));
+ else {
+ entry_brightness->read_proc = acpi_fuj02b1_read_brightness_state;
+ entry_brightness->write_proc = acpi_fuj02b1_write_brightness_state;
+ entry_brightness->data = acpi_driver_data(device);
+ }
+
+ if (!entry_pointer)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_FUJ02B1_FILE_POINTER));
+ else {
+ entry_pointer->read_proc = acpi_fuj02b1_read_pointer_state;
+ entry_pointer->write_proc = acpi_fuj02b1_write_pointer_state;
+ entry_pointer->data = acpi_driver_data(device);
+ }
+
+ return 0;
+}
+
+static int acpi_fuj02b1_remove_fs(struct acpi_device *device)
+{
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_remove_fs");
+
+ if (acpi_device_dir(device)) {
+ remove_proc_entry(acpi_device_bid(device), acpi_fuj02b1_dir);
+ acpi_device_dir(device) = NULL;
+ }
+
+ return 0;
+}
+
+
+/* --------------------------------------------------------------------------
+ Driver Interface
+ -------------------------------------------------------------------------- */
+
+void acpi_fuj02b1_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct acpi_fuj02b1 *fuj02b1 = (struct acpi_fuj02b1 *) data;
+ struct acpi_device *device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_notify");
+
+ if (!fuj02b1)
+ return;
+
+ if (acpi_bus_get_device(fuj02b1->handle, &device))
+ return;
+
+ switch (event) {
+ case ACPI_FUJ02B1_NOTIFY_STATUS:
+ acpi_fuj02b1_get_volume_state(fuj02b1);
+ if (fuj02b1->volume_changed == 1)
+ acpi_bus_generate_event(device, event, (u32) fuj02b1->volume_level | (fuj02b1->mute_state * 0x1000000) | 0x10000000);
+
+ acpi_fuj02b1_get_brightness_state(fuj02b1);
+ if (fuj02b1->brightness_changed == 1)
+ acpi_bus_generate_event(device, event, (u32) fuj02b1->brightness_level | 0x20000000);
+
+ acpi_fuj02b1_get_pointer_state(fuj02b1);
+ if (fuj02b1->pointer_changed == 1)
+ acpi_bus_generate_event(device, event, (u32) fuj02b1->pointer_state | 0x30000000);
+ break;
+ default:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Unsupported event [0x%x]\n", event));
+ break;
+ }
+
+ return;
+}
+
+int acpi_fuj02b1_add(struct acpi_device *device)
+{
+ struct acpi_fuj02b1 *fuj02b1 = NULL;
+ int result = 0;
+ int state = 0;
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_add");
+
+ if (!device)
+ return -EINVAL;
+
+ fuj02b1 = kmalloc(sizeof(struct acpi_fuj02b1), GFP_KERNEL);
+ if (!fuj02b1)
+ return -ENOMEM;
+ memset(fuj02b1, 0, sizeof(struct acpi_fuj02b1));
+
+ fuj02b1->handle = device->handle;
+ sprintf(acpi_device_name(device), "%s", ACPI_FUJ02B1_DEVICE_NAME);
+ sprintf(acpi_device_class(device), "%s", ACPI_FUJ02B1_CLASS);
+ acpi_driver_data(device) = fuj02b1;
+
+ result = acpi_bus_get_power(fuj02b1->handle, &state);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error reading power state\n"));
+ goto end;
+ }
+
+ result = acpi_fuj02b1_add_fs(device);
+ if (result)
+ goto end;
+
+ status = acpi_install_notify_handler(fuj02b1->handle,
+ ACPI_DEVICE_NOTIFY, acpi_fuj02b1_notify, fuj02b1);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n"));
+ result = -ENODEV;
+ goto end;
+ }
+
+ printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off");
+
+end:
+ if (result)
+ kfree(fuj02b1);
+
+ return result;
+}
+
+int acpi_fuj02b1_remove(struct acpi_device *device, int type)
+{
+ acpi_status status = AE_OK;
+ struct acpi_fuj02b1 *fuj02b1 = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_remove");
+
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+
+ fuj02b1 = (struct acpi_fuj02b1 *) acpi_driver_data(device);
+
+ status = acpi_remove_notify_handler(fuj02b1->handle,
+ ACPI_DEVICE_NOTIFY, acpi_fuj02b1_notify);
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error removing notify handler\n"));
+
+ acpi_fuj02b1_remove_fs(device);
+
+ kfree(fuj02b1);
+
+ return 0;
+}
+
+int __init acpi_fuj02b1_init(void)
+{
+ int result = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_fuj02b1_init");
+
+ acpi_fuj02b1_dir = proc_mkdir(ACPI_FUJ02B1_CLASS, acpi_root_dir);
+ if (!acpi_fuj02b1_dir)
+ return -ENODEV;
+
+ result = acpi_bus_register_driver(&acpi_fuj02b1_driver);
+ if (result < 0) {
+ remove_proc_entry(ACPI_FUJ02B1_CLASS, acpi_root_dir);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void __exit acpi_fuj02b1_exit(void)
+{
+ acpi_bus_unregister_driver(&acpi_fuj02b1_driver);
+
+ remove_proc_entry(ACPI_FUJ02B1_CLASS, acpi_root_dir);
+
+ return;
+}
+
+module_init(acpi_fuj02b1_init);
+module_exit(acpi_fuj02b1_exit);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 0:42 [PATCH] ACPI: add "Fujitsu laptop extras" module Jonathan Woithe
@ 2007-08-24 1:32 ` Matthew Garrett
2007-08-24 1:51 ` Jonathan Woithe
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Matthew Garrett @ 2007-08-24 1:32 UTC (permalink / raw)
To: Jonathan Woithe; +Cc: linux-acpi
> +static int acpi_fuj02b1_get_volume_state(void *data)
This probably wants to be exported as an ALSA mixer rather than a
special device in /proc.
> +static int acpi_fuj02b1_get_brightness_state(void *data)
And this certainly wants to use the backlight class.
> +static int acpi_fuj02b1_get_pointer_state(void *data)
Less sure about this one, but I'm not sure exactly what it's meant to
do - control whether the mouse pointer is enabled?
> + acpi_bus_generate_event(device, event, (u32) fuj02b1->volume_level | (fuj02b1->mute_state * 0x1000000) | 0x10000000);
ALSA is capable of generating events when the mixer volume changes, so I
don't think there's a need to explicitly generate an event here
(assuming you move the mixer over to ALSA)
> + acpi_bus_generate_event(device, event, (u32) fuj02b1->brightness_level | 0x20000000);
There's some disagreement over how to do this correctly. The currently
implemented way is for you to send KEY_BRIGHTNESSUP or
KEY_BRIGHTNESSDOWN and then let any userspace application check HAL to
determine whether it should do anything (we'd add an entry for Fujitsus
to indicate that the keys were merely notifications rather than
instructions), but there's also the argument that these keys should only
be used if they're acting as instructions to the software.
> + acpi_bus_generate_event(device, event, (u32) fuj02b1->pointer_state | 0x30000000);
What this one should do depends on what the pointer state actually means
:)
The idea here is to present consistent interfaces whenever possible,
allowing software to make use of them without having to know anything
about the specifics of the Fujitsu hardware. The drivers currently in
the kernel are gradually being ported over to this.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 1:32 ` Matthew Garrett
@ 2007-08-24 1:51 ` Jonathan Woithe
2007-08-24 2:33 ` Matthew Garrett
2007-08-24 2:13 ` Len Brown
` (2 subsequent siblings)
3 siblings, 1 reply; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-24 1:51 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Jonathan Woithe, linux-acpi
Thanks for the feedback.
> > +static int acpi_fuj02b1_get_volume_state(void *data)
>
> This probably wants to be exported as an ALSA mixer rather than a
> special device in /proc.
Or dropped altogether. As I mentioned, this patch is simply something I
picked up off the net. The only really important component I need from it
is the brightness control which will allow resume from suspend-to-ram to
turn the backlight back on. I personally don't see much point in the volume
control because the sound chipset (at least on my laptop) already works fine
through ALSA. Unless this is a totally separate volume control.
> > +static int acpi_fuj02b1_get_brightness_state(void *data)
>
> And this certainly wants to use the backlight class.
Sounds fine to me - I'm all for standardisation. Do you have any pointers
as to how I might get started on doing this? A "typical" driver I could
look at perhaps?
> > +static int acpi_fuj02b1_get_pointer_state(void *data)
>
> Less sure about this one, but I'm not sure exactly what it's meant to
> do - control whether the mouse pointer is enabled?
As far as I can tell yes - it controls the (hardware) mouse pointer. Again,
I'm happy to loose this one since I can see very little (if any) practical
use for it.
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->volume_level | (fuj02b1->mute_state * 0x1000000) | 0x10000000);
>
> ALSA is capable of generating events when the mixer volume changes, so I
> don't think there's a need to explicitly generate an event here
> (assuming you move the mixer over to ALSA)
As I mentioned, I'd be happy to drop the mixer thing (at least for now)
unless I can find any evidence that it's even remotely useful.
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->brightness_level | 0x20000000);
>
> There's some disagreement over how to do this correctly. The currently
> implemented way is for you to send KEY_BRIGHTNESSUP or
> KEY_BRIGHTNESSDOWN and then let any userspace application check HAL to
> determine whether it should do anything (we'd add an entry for Fujitsus
> to indicate that the keys were merely notifications rather than
> instructions), but there's also the argument that these keys should only
> be used if they're acting as instructions to the software.
In the first instance I suspect there's probably no need to notify userspace
of when these keys are pressed. The keys themselves already affect the
screen brightness via the hardware so there seems little point on
complicating things by passing them onto userspace.
> The idea here is to present consistent interfaces whenever possible,
> allowing software to make use of them without having to know anything
> about the specifics of the Fujitsu hardware. The drivers currently in
> the kernel are gradually being ported over to this.
Sounds great in theory. Are there any documents around which summarise the
APCI system and how it fits in with the whole backlight class? Or is it a
case of having to deduce all this by going though the source?
Regards
jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 1:32 ` Matthew Garrett
2007-08-24 1:51 ` Jonathan Woithe
@ 2007-08-24 2:13 ` Len Brown
2007-08-24 3:11 ` Len Brown
2007-08-24 3:12 ` [PATCH] ACPI: add "Fujitsu laptop extras" module Jonathan Woithe
2007-08-24 3:55 ` Zhang Rui
2007-08-24 7:24 ` Adrian Yee
3 siblings, 2 replies; 15+ messages in thread
From: Len Brown @ 2007-08-24 2:13 UTC (permalink / raw)
To: Matthew Garrett, Jonathan Woithe; +Cc: linux-acpi
I agree with everything Matthew wrote.
Also, please move it to drivers/misc, to keep msi-laptop,
sony-laptop, asus-laptop, and thinkpad-acpi company.
toshiba-acpi is in drivers/acpi just because it is being neglected --
but the new scheme is for platform specific drivers that
use ACPI is to put them in drivers/misc; and /drivers/acpi
is for stuff that implements generic ACPI code.
You might consider naming it fujitsu-laptop as well,
since the driver depends on ACPI, but it really exists
to provide laptop features, not to implement part of the ACPI spec...
fuj02b1_acpi.c may be accurate, but nobody will know what it is.
Along those lines, it is generally a good idea to put
if (acpi_disabled)
return -ENODEV;
in the init function if the driver is worthless without ACPI.
Also, the driver needs somebody to volunteer to be
its maintainer before it can be merged.
Finally, please run it through scripts/Lindent before the next edition.
thanks,
-Len
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 1:51 ` Jonathan Woithe
@ 2007-08-24 2:33 ` Matthew Garrett
0 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2007-08-24 2:33 UTC (permalink / raw)
To: Jonathan Woithe; +Cc: linux-acpi
On Fri, Aug 24, 2007 at 11:21:38AM +0930, Jonathan Woithe wrote:
> > This probably wants to be exported as an ALSA mixer rather than a
> > special device in /proc.
>
> Or dropped altogether. As I mentioned, this patch is simply something I
> picked up off the net. The only really important component I need from it
> is the brightness control which will allow resume from suspend-to-ram to
> turn the backlight back on. I personally don't see much point in the volume
> control because the sound chipset (at least on my laptop) already works fine
> through ALSA. Unless this is a totally separate volume control.
Yeah. It would be good if you could figure out if it alters behaviour
entirely independently of the rest of the mixer hardware (Thinkpads do
that) - the easiest way is probably to set it to 0 and see if you can
still get the machine to make noise after playing with the soundcard
mixers. If not, it's worth exporting. If it still is, do it.
> > And this certainly wants to use the backlight class.
>
> Sounds fine to me - I'm all for standardisation. Do you have any pointers
> as to how I might get started on doing this? A "typical" driver I could
> look at perhaps?
Take a look at asus_acpi in recent kernels, and also the drivers under
drivers/video/backlight
> > Less sure about this one, but I'm not sure exactly what it's meant to
> > do - control whether the mouse pointer is enabled?
>
> As far as I can tell yes - it controls the (hardware) mouse pointer. Again,
> I'm happy to loose this one since I can see very little (if any) practical
> use for it.
It sounds potentially useful (some users seem to like toggling that for
some reason), but I'm not sure what the best way of exporting it would
be. Is there a key on the keyboard that controls it? If so, does it work
without needing a driver?
> > There's some disagreement over how to do this correctly. The currently
> > implemented way is for you to send KEY_BRIGHTNESSUP or
> > KEY_BRIGHTNESSDOWN and then let any userspace application check HAL to
> > determine whether it should do anything (we'd add an entry for Fujitsus
> > to indicate that the keys were merely notifications rather than
> > instructions), but there's also the argument that these keys should only
> > be used if they're acting as instructions to the software.
>
> In the first instance I suspect there's probably no need to notify userspace
> of when these keys are pressed. The keys themselves already affect the
> screen brightness via the hardware so there seems little point on
> complicating things by passing them onto userspace.
The main reason for doing so is to let a userspace application pop up a
little box to show what the screen brightness is.
> > The idea here is to present consistent interfaces whenever possible,
> > allowing software to make use of them without having to know anything
> > about the specifics of the Fujitsu hardware. The drivers currently in
> > the kernel are gradually being ported over to this.
>
> Sounds great in theory. Are there any documents around which summarise the
> APCI system and how it fits in with the whole backlight class? Or is it a
> case of having to deduce all this by going though the source?
I haven't seen any docs on this - I just copied stuff out of the
existing ones.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 2:13 ` Len Brown
@ 2007-08-24 3:11 ` Len Brown
2007-08-24 3:15 ` Jonathan Woithe
2007-08-24 3:12 ` [PATCH] ACPI: add "Fujitsu laptop extras" module Jonathan Woithe
1 sibling, 1 reply; 15+ messages in thread
From: Len Brown @ 2007-08-24 3:11 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Jonathan Woithe, linux-acpi
On Thursday 23 August 2007 22:13, Len Brown wrote:
> I agree with everything Matthew wrote.
>
> Also, please move it to drivers/misc, to keep msi-laptop,
> sony-laptop, asus-laptop, and thinkpad-acpi company.
>
> toshiba-acpi is in drivers/acpi just because it is being neglected --
> but the new scheme is for platform specific drivers that
> use ACPI is to put them in drivers/misc; and /drivers/acpi
> is for stuff that implements generic ACPI code.
>
> You might consider naming it fujitsu-laptop as well,
> since the driver depends on ACPI, but it really exists
> to provide laptop features, not to implement part of the ACPI spec...
> fuj02b1_acpi.c may be accurate, but nobody will know what it is.
>
> Along those lines, it is generally a good idea to put
> if (acpi_disabled)
> return -ENODEV;
>
> in the init function if the driver is worthless without ACPI.
>
> Also, the driver needs somebody to volunteer to be
> its maintainer before it can be merged.
>
> Finally, please run it through scripts/Lindent before the next edition.
Oh, i forgot to mention also...
There should be no new files created under /proc/acpi
for platform specific drivers.
thanks,
-Len
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 2:13 ` Len Brown
2007-08-24 3:11 ` Len Brown
@ 2007-08-24 3:12 ` Jonathan Woithe
1 sibling, 0 replies; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-24 3:12 UTC (permalink / raw)
To: Len Brown; +Cc: Matthew Garrett, Jonathan Woithe, linux-acpi
> I agree with everything Matthew wrote.
No problem - thanks to both of you for the feedback.
> Also, please move it to drivers/misc, to keep msi-laptop,
> sony-laptop, asus-laptop, and thinkpad-acpi company.
Will do. I assume that this list would still be the most appropriate place
to submit such a driver?
> You might consider naming it fujitsu-laptop as well,
> since the driver depends on ACPI, but it really exists
> to provide laptop features, not to implement part of the ACPI spec...
> fuj02b1_acpi.c may be accurate, but nobody will know what it is.
I agree with this.
> Along those lines, it is generally a good idea to put
> if (acpi_disabled)
> return -ENODEV;
Agreed.
> Also, the driver needs somebody to volunteer to be
> its maintainer before it can be merged.
At this stage I would be happy to maintain it.
> Finally, please run it through scripts/Lindent before the next edition.
Will do.
Thanks once again for your help and suggestions. I shall rework the patch
in due course.
Regards
jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 3:11 ` Len Brown
@ 2007-08-24 3:15 ` Jonathan Woithe
2007-08-24 4:23 ` Len Brown
0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-24 3:15 UTC (permalink / raw)
To: Len Brown; +Cc: Matthew Garrett, Jonathan Woithe, linux-acpi
> Oh, i forgot to mention also...
> There should be no new files created under /proc/acpi
> for platform specific drivers.
Sure. In the case of the backlight control (which is the thing I most care
about) this will be taken care of by virue of utilising the backlight class
as per Matthew's email. If it did prove useful to export the mouse pointer
control for example (which at this stage is uncertain) what would be the
most appropriate location for the associated virtual files - something under
/sys?
Regards
jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 1:32 ` Matthew Garrett
2007-08-24 1:51 ` Jonathan Woithe
2007-08-24 2:13 ` Len Brown
@ 2007-08-24 3:55 ` Zhang Rui
2007-08-24 4:12 ` Matthew Garrett
2007-08-24 7:24 ` Adrian Yee
3 siblings, 1 reply; 15+ messages in thread
From: Zhang Rui @ 2007-08-24 3:55 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Jonathan Woithe, linux-acpi
On Fri, 2007-08-24 at 02:32 +0100, Matthew Garrett wrote:
> > +static int acpi_fuj02b1_get_volume_state(void *data)
>
> This probably wants to be exported as an ALSA mixer rather than a
> special device in /proc.
>
> > +static int acpi_fuj02b1_get_brightness_state(void *data)
>
> And this certainly wants to use the backlight class.
>
> > +static int acpi_fuj02b1_get_pointer_state(void *data)
>
> Less sure about this one, but I'm not sure exactly what it's meant to
> do - control whether the mouse pointer is enabled?
>
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->volume_level | (fuj02b1->mute_state * 0x1000000) | 0x10000000);
>
> ALSA is capable of generating events when the mixer volume changes, so I
> don't think there's a need to explicitly generate an event here
> (assuming you move the mixer over to ALSA)
>
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->brightness_level | 0x20000000);
>
> There's some disagreement over how to do this correctly. The currently
> implemented way is for you to send KEY_BRIGHTNESSUP or
> KEY_BRIGHTNESSDOWN and then let any userspace application check HAL to
> determine whether it should do anything (we'd add an entry for Fujitsus
> to indicate that the keys were merely notifications rather than
> instructions), but there's also the argument that these keys should only
> be used if they're acting as instructions to the software.
>
I have the same question for ACPI video driver.
Take KEY_BRIGHTNESSUP/KEY_BRIGHTNESSDOWN for example, if ACPI video
driver gets such a notification, it will change the brightness level
first and then send an event to user space.
But IMO, what the driver need to do is to provide a user space I/F
first, /sys/class/backlight/acpi_videox/... in this case, and send a
notification when keys are pressed.
Any comments about this?
I'll send a patch to make ACPI video driver do nothing but export the
events to user space in the notify handler if you guys think it's okay.
Thanks,
Rui
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->pointer_state | 0x30000000);
>
> What this one should do depends on what the pointer state actually means
> :)
>
> The idea here is to present consistent interfaces whenever possible,
> allowing software to make use of them without having to know anything
> about the specifics of the Fujitsu hardware. The drivers currently in
> the kernel are gradually being ported over to this.
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 3:55 ` Zhang Rui
@ 2007-08-24 4:12 ` Matthew Garrett
2007-08-25 6:05 ` Len Brown
0 siblings, 1 reply; 15+ messages in thread
From: Matthew Garrett @ 2007-08-24 4:12 UTC (permalink / raw)
To: Zhang Rui; +Cc: Jonathan Woithe, linux-acpi
On Fri, Aug 24, 2007 at 11:55:41AM +0800, Zhang Rui wrote:
> I have the same question for ACPI video driver.
> Take KEY_BRIGHTNESSUP/KEY_BRIGHTNESSDOWN for example, if ACPI video
> driver gets such a notification, it will change the brightness level
> first and then send an event to user space.
The X people would prefer that the kernel not change the brightness
itself, where possible. In the cases where drivers know how to control
the backlight hardware themselves (most new Intel hardware, nvidia stuff
since 2005ish, that sort of thing) it's likely that they'll be able to
provide much more control than the level provided via the ACPI
interface.
> I'll send a patch to make ACPI video driver do nothing but export the
> events to user space in the notify handler if you guys think it's okay.
I think that's the right thing to do, but you might want to make it a
module option to begin with. That way you can printk that the behaviour
will change in the future, and then flip the default in a few months.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 3:15 ` Jonathan Woithe
@ 2007-08-24 4:23 ` Len Brown
2007-08-27 3:21 ` [PATCH] ACPI: add "Fujitsu laptop extras" module, take 2 Jonathan Woithe
0 siblings, 1 reply; 15+ messages in thread
From: Len Brown @ 2007-08-24 4:23 UTC (permalink / raw)
To: Jonathan Woithe; +Cc: Matthew Garrett, linux-acpi
On Thursday 23 August 2007 23:15, Jonathan Woithe wrote:
> > Oh, i forgot to mention also...
> > There should be no new files created under /proc/acpi
> > for platform specific drivers.
>
> Sure. In the case of the backlight control (which is the thing I most care
> about) this will be taken care of by virue of utilising the backlight class
> as per Matthew's email. If it did prove useful to export the mouse pointer
> control for example (which at this stage is uncertain) what would be the
> most appropriate location for the associated virtual files - something under
> /sys?
yes, certainly something outside of /proc.
ideally something _generic_ under /sys.
If device specific and the device exists in sysfs already, then there.
But there can be platform specific hooks in sysfs too.
thinkpad-acpi stuffs some platform specific junk under /sys/devices/platform/
see Documentation/thinkpad-acpi.txt
your fujitsu driver will probably be a lot like the msi-laptop.c driver
when you're done with it, maybe even simpler.
cheers,
-Len
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 1:32 ` Matthew Garrett
` (2 preceding siblings ...)
2007-08-24 3:55 ` Zhang Rui
@ 2007-08-24 7:24 ` Adrian Yee
2007-08-24 7:31 ` Jonathan Woithe
3 siblings, 1 reply; 15+ messages in thread
From: Adrian Yee @ 2007-08-24 7:24 UTC (permalink / raw)
To: Matthew Garrett, Jonathan Woithe; +Cc: linux-acpi
Hi,
I was the person who cleaned up the code a couple years back. I don't own a
Fujitsu notebook anymore, but here's some information from what I remember.
Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > +static int acpi_fuj02b1_get_volume_state(void *data)
>
> This probably wants to be exported as an ALSA mixer rather than a
> special device in /proc.
My S6010 had hardware volume control (it was separate from what was ALSA
controlled). I'm not sure if this is still the case with the Fujitsu's S and
P-series notebooks.
> > +static int acpi_fuj02b1_get_pointer_state(void *data)
>
> Less sure about this one, but I'm not sure exactly what it's meant to
> do - control whether the mouse pointer is enabled?
I never used this, but I think it gives the user the ability to disable the
built-in touchpad. Probably driver dependent.
> > + acpi_bus_generate_event(device, event, (u32) fuj02b1->volume_level |
> (fuj02b1->mute_state * 0x1000000) | 0x10000000);
>
> ALSA is capable of generating events when the mixer volume changes, so I
> don't think there's a need to explicitly generate an event here
> (assuming you move the mixer over to ALSA)
Since the buttons control the hardware volume control, I believe the events were
more for displaying OSD volume status.
Adrian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 7:24 ` Adrian Yee
@ 2007-08-24 7:31 ` Jonathan Woithe
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-24 7:31 UTC (permalink / raw)
To: Adrian Yee; +Cc: Matthew Garrett, Jonathan Woithe, linux-acpi
Hi Adrian
> I was the person who cleaned up the code a couple years back. I don't own a
> Fujitsu notebook anymore, but here's some information from what I remember.
>
> Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> > > +static int acpi_fuj02b1_get_volume_state(void *data)
> >
> > This probably wants to be exported as an ALSA mixer rather than a
> > special device in /proc.
>
> My S6010 had hardware volume control (it was separate from what was ALSA
> controlled). I'm not sure if this is still the case with the Fujitsu's S and
> P-series notebooks.
:
> Since the buttons control the hardware volume control, I believe the events were
> more for displaying OSD volume status.
Thanks for the information. I'll do some more tests over the next week or
so to see how this relates to the S7xxx series. Even so, given that it was
obviously useful for the earlier series we should probably still leave it
in.
> > > +static int acpi_fuj02b1_get_pointer_state(void *data)
> >
> > Less sure about this one, but I'm not sure exactly what it's meant to
> > do - control whether the mouse pointer is enabled?
>
> I never used this, but I think it gives the user the ability to disable the
> built-in touchpad. Probably driver dependent.
Ah right - that would make more sense than disabling the hardware graphics
cursor.
Regards
jonathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] ACPI: add "Fujitsu laptop extras" module
2007-08-24 4:12 ` Matthew Garrett
@ 2007-08-25 6:05 ` Len Brown
0 siblings, 0 replies; 15+ messages in thread
From: Len Brown @ 2007-08-25 6:05 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Zhang Rui, Jonathan Woithe, linux-acpi
On Friday 24 August 2007 00:12, Matthew Garrett wrote:
> On Fri, Aug 24, 2007 at 11:55:41AM +0800, Zhang Rui wrote:
>
> > I have the same question for ACPI video driver.
> > Take KEY_BRIGHTNESSUP/KEY_BRIGHTNESSDOWN for example, if ACPI video
> > driver gets such a notification, it will change the brightness level
> > first and then send an event to user space.
>
> The X people would prefer that the kernel not change the brightness
> itself, where possible. In the cases where drivers know how to control
> the backlight hardware themselves (most new Intel hardware, nvidia stuff
> since 2005ish, that sort of thing) it's likely that they'll be able to
> provide much more control than the level provided via the ACPI
> interface.
>
> > I'll send a patch to make ACPI video driver do nothing but export the
> > events to user space in the notify handler if you guys think it's okay.
>
> I think that's the right thing to do, but you might want to make it a
> module option to begin with. That way you can printk that the behaviour
> will change in the future, and then flip the default in a few months.
We must handle two modes:
1. VGA mode, no X
Control the video in the kernel via ACPI methods to talk to the BIOS.
This is known to work on multiple laptops today.
I don't see the utility in sending the hotkey events to user-space
in this mode, but I also don't see the harm, so lets keep them
as an FYI in case some graphics software doesn't know how to
control the video but wants the event to re-probe or something.
2. Graphics mode, X is running
While sometimes programming the video behind X's back
using the kernel and BIOS ACPI entry points works,
this is generally a bad idea.
Here we need to disable the ACPI entry points that control video,
and do nothing but send the input events to user-space
to be picked up by the X server.
Clearly there needs to be a mode bit.
The mode bit should default to case #1 --
as that is what we are running today --
and when X knows to look for the input events
and has the ability to switch modes natively, it should
set the mode bit to switch us to case #2.
The mode bit should probably live in the CONFIG_VIDEO_OUTPUT_CONTROL,
eg. under driers/video/output.c with some generic name that in this
case the acpi video driver registers for.
Rui, can you follow up on this?
thanks,
-Len
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] ACPI: add "Fujitsu laptop extras" module, take 2
2007-08-24 4:23 ` Len Brown
@ 2007-08-27 3:21 ` Jonathan Woithe
0 siblings, 0 replies; 15+ messages in thread
From: Jonathan Woithe @ 2007-08-27 3:21 UTC (permalink / raw)
To: Len Brown; +Cc: Jonathan Woithe, Matthew Garrett, linux-acpi
Hi guys
Here is a new version of the Fujitsu laptop extras patch for consideration
and/or comment. I *think* I've addressed most of what was commented on in
reply to the previous submission. Of significant note:
* for now the mixer and pointer components of the interface are gone since
those buttons don't do anything in hardware on my machine (see below) so
I'm not sure what they are meant to do. In any case I don't need them,
so I'd rather get the important infrastructure in place first - the rest
can be added over time.
* the standard backlight class is now used for the LCD brightness
functionality.
* at the moment I don't pass the button presses back to userspace because
the hardware does the changes. I note that this whole behavioural area
is currently under discussion so this might change in future.
* the module has been renamed fujitsu-laptop and resides in drivers/misc/.
* the module creates platform/fujitsu-laptop/ to park platform-specific
files. For now all I do is drop the backlight interface in there (like
msi-laptop does) but in time the pointer/volume stuff might also go there
if these are implemented. No new files are created in /proc/.
* scripts/Lindent has been used.
In relation to the pointer and volume buttons, in contrast to the brightness
buttons these don't appear to have any hardware effect at all on the S7020.
Obviously their implementation on the S7020 is in software which seems to
differ from previous P- and S-series laptops. I due course I intend to
add these features but they are not my highest priority.
The new code was tested as a module and loaded/unloaded correctly.
Brightness control and feedback was as expected on a Fujitsu S7020.
Signed-off-by: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Regards
jonathan
diff -ruN linux-2.6.22.1-rt9-orig/drivers/misc/Kconfig linux-2.6.22.1-rt9-new/drivers/misc/Kconfig
--- linux-2.6.22.1-rt9-orig/drivers/misc/Kconfig 2007-08-12 09:23:56.000000000 +0930
+++ linux-2.6.22.1-rt9-new/drivers/misc/Kconfig 2007-08-26 21:11:56.000000000 +0930
@@ -97,6 +97,21 @@
If you have an ACPI-compatible ASUS laptop, say Y or M here.
+config FUJITSU_LAPTOP
+ tristate "Fujitsu Laptop Extras"
+ depends on X86
+ depends on ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is a driver for laptops built by Fujitsu:
+
+ * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
+ * Possibly other Fujitsu laptop models
+
+ It adds support for LCD brightness control.
+
+ If you have a Fujitsu laptop, say Y or M here.
+
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on X86
diff -ruN linux-2.6.22.1-rt9-orig/drivers/misc/Makefile linux-2.6.22.1-rt9-new/drivers/misc/Makefile
--- linux-2.6.22.1-rt9-orig/drivers/misc/Makefile 2007-08-12 09:23:56.000000000 +0930
+++ linux-2.6.22.1-rt9-new/drivers/misc/Makefile 2007-08-26 21:12:48.000000000 +0930
@@ -14,3 +14,4 @@
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
diff -ruN linux-2.6.22.1-rt9-orig/drivers/misc/fujitsu-laptop.c linux-2.6.22.1-rt9-new/drivers/misc/fujitsu-laptop.c
--- linux-2.6.22.1-rt9-orig/drivers/misc/fujitsu-laptop.c 1970-01-01 09:30:00.000000000 +0930
+++ linux-2.6.22.1-rt9-new/drivers/misc/fujitsu-laptop.c 2007-08-26 22:00:48.000000000 +0930
@@ -0,0 +1,373 @@
+/*-*-linux-c-*-*/
+
+/*
+ Copyright (C) 2007 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
+ Based on earlier work:
+ Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
+ Adrian Yee <brewt-fujitsu@brewt.org>
+
+ Templated from msi-laptop.c which is copyright by its respective authors.
+
+ 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 of the License, 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+ */
+
+/*
+ * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional
+ * features made available on a range of Fujitsu laptops including the
+ * P2xxx/P5xxx/S6xxx/S7xxx series.
+ *
+ * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/;
+ * others may be added at a later date.
+ *
+ * lcd_level - Screen brightness: contains a single integer in the
+ * range 0..7. (rw)
+ *
+ * In addition to these platform device attributes the driver
+ * registers itself in the Linux backlight control subsystem and is
+ * available to userspace under /sys/class/backlight/fujitsu-laptop/.
+ *
+ * This driver has been tested on a Fujitsu Lifebook S7020. It should
+ * work on most P-series and S-series Lifebooks, but YMMV.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/autoconf.h>
+
+#define FUJITSU_DRIVER_VERSION "0.1"
+
+#define FUJITSU_LCD_N_LEVELS 8
+
+#define ACPI_FUJITSU_CLASS "fujitsu"
+#define ACPI_FUJITSU_HID "FUJ02B1"
+#define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI extras driver"
+#define ACPI_FUJITSU_DEVICE_NAME "Fujitsu FUJ02B1"
+
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
+
+struct fujitsu_t {
+ acpi_handle acpi_handle;
+ struct backlight_device *bl_device;
+ struct platform_device *pf_device;
+
+ unsigned long fuj02b1_state;
+ unsigned int brightness_changed;
+ unsigned int brightness_level;
+};
+
+static struct fujitsu_t *fujitsu;
+
+/* Hardware access */
+
+static int set_lcd_level(int level)
+{
+ acpi_status status = AE_OK;
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list arg_list = { 1, &arg0 };
+ acpi_handle handle = NULL;
+
+ if (level < 0 || level >= FUJITSU_LCD_N_LEVELS)
+ return -EINVAL;
+
+ if (!fujitsu)
+ return -EINVAL;
+
+ status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SBLL not present\n"));
+ return -ENODEV;
+ }
+
+ arg0.integer.value = level;
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int get_lcd_level(void)
+{
+ unsigned long state = 0;
+ acpi_status status = AE_OK;
+
+ // Get the Brightness
+ status =
+ acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state);
+ if (status < 0)
+ return status;
+
+ fujitsu->fuj02b1_state = state;
+ fujitsu->brightness_level = state & 0x0fffffff;
+
+ if (state & 0x80000000)
+ fujitsu->brightness_changed = 1;
+ else
+ fujitsu->brightness_changed = 0;
+
+ if (status < 0)
+ return status;
+
+ return fujitsu->brightness_level;
+}
+
+/* Backlight device stuff */
+
+static int bl_get_brightness(struct backlight_device *b)
+{
+ return get_lcd_level();
+}
+
+static int bl_update_status(struct backlight_device *b)
+{
+ return set_lcd_level(b->props.brightness);
+}
+
+static struct backlight_ops fujitsubl_ops = {
+ .get_brightness = bl_get_brightness,
+ .update_status = bl_update_status,
+};
+
+/* Platform device */
+
+static ssize_t show_lcd_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ int ret;
+
+ ret = get_lcd_level();
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t store_lcd_level(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+
+ int level, ret;
+
+ if (sscanf(buf, "%i", &level) != 1
+ || (level < 0 || level >= FUJITSU_LCD_N_LEVELS))
+ return -EINVAL;
+
+ ret = set_lcd_level(level);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
+
+static struct attribute *fujitsupf_attributes[] = {
+ &dev_attr_lcd_level.attr,
+ NULL
+};
+
+static struct attribute_group fujitsupf_attribute_group = {
+ .attrs = fujitsupf_attributes
+};
+
+static struct platform_driver fujitsupf_driver = {
+ .driver = {
+ .name = "fujitsu-laptop",
+ .owner = THIS_MODULE,
+ }
+};
+
+/* ACPI device */
+
+int acpi_fujitsu_add(struct acpi_device *device)
+{
+ int result = 0;
+ int state = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_fujitsu_add");
+
+ if (!device)
+ return -EINVAL;
+
+ fujitsu->acpi_handle = device->handle;
+ sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME);
+ sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
+ acpi_driver_data(device) = fujitsu;
+
+ result = acpi_bus_get_power(fujitsu->acpi_handle, &state);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error reading power state\n"));
+ goto end;
+ }
+
+ printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ !device->power.state ? "on" : "off");
+
+ end:
+
+ return result;
+}
+
+int acpi_fujitsu_remove(struct acpi_device *device, int type)
+{
+ ACPI_FUNCTION_TRACE("acpi_fujitsu_remove");
+
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+ fujitsu->acpi_handle = 0;
+
+ return 0;
+}
+
+static struct acpi_driver acpi_fujitsu_driver = {
+ .name = ACPI_FUJITSU_DRIVER_NAME,
+ .class = ACPI_FUJITSU_CLASS,
+ .ids = ACPI_FUJITSU_HID,
+ .ops = {
+ .add = acpi_fujitsu_add,
+ .remove = acpi_fujitsu_remove,
+ },
+};
+
+/* Initialization */
+
+static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
+ {
+ .ident = "Fujitsu S7020",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S7020"),
+ }
+ },
+ {
+ .ident = "Fujitsu generic laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ }
+ },
+ {}
+};
+
+static int __init fujitsu_init(void)
+{
+ int ret, result;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ if (!force && !dmi_check_system(fujitsu_dmi_table))
+ return -ENODEV;
+
+ fujitsu = kmalloc(sizeof(struct fujitsu_t), GFP_KERNEL);
+ if (!fujitsu)
+ return -ENOMEM;
+ memset(fujitsu, 0, sizeof(struct fujitsu_t));
+
+ result = acpi_bus_register_driver(&acpi_fujitsu_driver);
+ if (result < 0)
+ return -ENODEV;
+
+ /* Register backlight stuff */
+
+ fujitsu->bl_device =
+ backlight_device_register("fujitsu-laptop", NULL, NULL,
+ &fujitsubl_ops);
+ if (IS_ERR(fujitsu->bl_device))
+ return PTR_ERR(fujitsu->bl_device);
+
+ fujitsu->bl_device->props.max_brightness = FUJITSU_LCD_N_LEVELS - 1,
+ ret = platform_driver_register(&fujitsupf_driver);
+ if (ret)
+ goto fail_backlight;
+
+ /* Register platform stuff */
+
+ fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1);
+ if (!fujitsu->pf_device) {
+ ret = -ENOMEM;
+ goto fail_platform_driver;
+ }
+
+ ret = platform_device_add(fujitsu->pf_device);
+ if (ret)
+ goto fail_platform_device1;
+
+ ret =
+ sysfs_create_group(&fujitsu->pf_device->dev.kobj,
+ &fujitsupf_attribute_group);
+ if (ret)
+ goto fail_platform_device2;
+
+ printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
+ " successfully loaded.\n");
+
+ return 0;
+
+ fail_platform_device2:
+
+ platform_device_del(fujitsu->pf_device);
+
+ fail_platform_device1:
+
+ platform_device_put(fujitsu->pf_device);
+
+ fail_platform_driver:
+
+ platform_driver_unregister(&fujitsupf_driver);
+
+ fail_backlight:
+
+ backlight_device_unregister(fujitsu->bl_device);
+
+ kfree(fujitsu);
+
+ return ret;
+}
+
+static void __exit fujitsu_cleanup(void)
+{
+ sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
+ &fujitsupf_attribute_group);
+ platform_device_unregister(fujitsu->pf_device);
+ platform_driver_unregister(&fujitsupf_driver);
+ backlight_device_unregister(fujitsu->bl_device);
+
+ acpi_bus_unregister_driver(&acpi_fujitsu_driver);
+
+ kfree(fujitsu);
+
+ printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n");
+}
+
+module_init(fujitsu_init);
+module_exit(fujitsu_cleanup);
+
+MODULE_AUTHOR("Jonathan Woithe");
+MODULE_DESCRIPTION("Fujitsu laptop extras support");
+MODULE_VERSION(FUJITSU_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2007-08-27 3:22 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-24 0:42 [PATCH] ACPI: add "Fujitsu laptop extras" module Jonathan Woithe
2007-08-24 1:32 ` Matthew Garrett
2007-08-24 1:51 ` Jonathan Woithe
2007-08-24 2:33 ` Matthew Garrett
2007-08-24 2:13 ` Len Brown
2007-08-24 3:11 ` Len Brown
2007-08-24 3:15 ` Jonathan Woithe
2007-08-24 4:23 ` Len Brown
2007-08-27 3:21 ` [PATCH] ACPI: add "Fujitsu laptop extras" module, take 2 Jonathan Woithe
2007-08-24 3:12 ` [PATCH] ACPI: add "Fujitsu laptop extras" module Jonathan Woithe
2007-08-24 3:55 ` Zhang Rui
2007-08-24 4:12 ` Matthew Garrett
2007-08-25 6:05 ` Len Brown
2007-08-24 7:24 ` Adrian Yee
2007-08-24 7:31 ` Jonathan Woithe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).