summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2009-06-17 11:51:54 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2009-06-17 11:51:54 +1000
commit10c72cbd311a9b506e123b5cf7bdbce5d06a69e5 (patch)
tree34c9480bbdab362493d863b1fcdb7edfde284e8c
parent29b142304e91df6d012182817000728224f212d5 (diff)
Revert "Merge branch 'oqo-wmi-EXPECT-REFRESH' into test"
This reverts commit bc8c4c9333ff8346031db85f395ecc73925230c3, reversing changes made to 8bea756d993c60fea0970d63002148ce58f6a8a6.
-rw-r--r--MAINTAINERS5
-rw-r--r--drivers/platform/x86/Kconfig14
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/oqo-wmi.c941
4 files changed, 0 insertions, 961 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 2f284d07e502..179d824be272 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4343,11 +4343,6 @@ F: arch/*/oprofile/
F: drivers/oprofile/
F: include/linux/oprofile.h
-OQO WMI EXTRAS DRIVER
-P: Matthew Garrett
-M: mjg59@srcf.ucam.org
-S: Maintained
-
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
P: Mark Fasheh
M: mfasheh@suse.com
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7f86a434b758..1d303c809275 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -143,20 +143,6 @@ config MSI_LAPTOP
If you have an MSI S270 laptop, say Y or M here.
-config OQO_WMI
- tristate "OQO WMI extras"
- depends on ACPI_WMI
- depends on INPUT
- depends on RFKILL
- depends on BACKLIGHT_CLASS_DEVICE
- select INPUT_POLLDEV
- help
- Say Y here if you want to support rfkill and backlight control on
- series 2 OQO handheld devices.
-
- To compile this driver as a module, choose M here: the module will
- be called oqo-wmi.
-
config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 1637378ad3f4..e40c7bd1b87e 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
-obj-$(CONFIG_OQO_WMI) += oqo-wmi.o
obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ACPI_WMI) += wmi.o
diff --git a/drivers/platform/x86/oqo-wmi.c b/drivers/platform/x86/oqo-wmi.c
deleted file mode 100644
index 0a88af82f127..000000000000
--- a/drivers/platform/x86/oqo-wmi.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
- * OQO WMI UPMC Extras
- *
- * Copyright (C) 2008 Brian S. Julin <bri@abrij.org>
- *
- * Based on acer-wmi:
- * Copyright (C) 2007-2008 Carlos Corbacho <cathectic@gmail.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
- */
-
-/*
- * NOTE: You need to turn SMI on in BIOS (if dmidecode works, you already have)
- * NOTE: acpi-wmi support mandatory
- * NOTE: backlight and inputdev support a must, ifdefs will come later
- */
-
-/*
- *
- * 0.3: added WLAN enable switch, restore settings on unload,
- * resume/suspend handling
- * 0.2: Still not production-ready, but added ambient light sensor,
- * backlight, and it prints the unit serial number to dmesg (do
- * not know where to make that available to userspace yet.)
- * 0.1: This is a first cut. Plan to reboot after playing with this.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/dmi.h>
-#include <linux/backlight.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/acpi.h>
-#include <linux/i8042.h>
-#include <linux/input-polldev.h>
-#include <linux/rfkill.h>
-
-#include <acpi/acpi_drivers.h>
-
-MODULE_AUTHOR("Brian Julin");
-MODULE_DESCRIPTION("OQO UPMC WMI Extras Driver");
-MODULE_LICENSE("GPL");
-
-#define OQO_LOGPREFIX "oqo-wmi: "
-#define OQO_ERR KERN_ERR OQO_LOGPREFIX
-#define OQO_NOTICE KERN_NOTICE OQO_LOGPREFIX
-#define OQO_INFO KERN_INFO OQO_LOGPREFIX
-
-#define OQO_KINE_MAXTRY 3
-
-/* Store defined devices globally since we only have one instance. */
-static struct platform_device *oqo_platform_device;
-static struct backlight_device *oqo_backlight_device;
-static struct rfkill *oqo_rfkill;
-static struct input_dev *oqo_kine;
-static struct input_polled_dev *oqo_kine_polled;
-
-/* Likewise store current and original settings globally. */
-struct oqo_settings {
- int lid_wakes; /* not sure if ACPI handles/needs help here */
- int kine_itvl;
- int bl_bright;
-};
-
-static struct oqo_settings orig, curr;
-
-/* Some of this code is left like in acer-wmi so we can add the older
- Model 01 and any future models more easily, but we should not expect
- it to be as complicated as Acer given each model is a leap rather than
- a subtle variant on the last, so we aren't using "quirks" perse. Not
- sure if there is any real difference for our purposes between the o2
- and e2.
-*/
-struct oqo_model {
- const char *model;
- u16 model_subs;
-};
-#define MODEL_SUB_OQO_O2_SMB0 3
-
-static struct oqo_model oqo_models[] = {
- {
- .model = "Model 2",
- .model_subs = MODEL_SUB_OQO_O2_SMB0,
- },
- {}
-};
-
-static struct oqo_model *model;
-
-static int force;
-module_param(force, bool, 0644);
-MODULE_PARM_DESC(force, "Force WMI detection even if DMI detection failed");
-
-/*
- * OQO Model 2 SMBUS registers
- * We are just using WMI to read the Cx700 smbus, to share the
- * ACPI mutex (what may also eventually work in VMs/win32)
- * Using i2c-viapro directly could interfere with PM.
- */
-
-#define OQO_O2_SMB0_WWAN_DSBL_ADDR 0x19
-#define OQO_O2_SMB0_WWAN_DSBL_MASK 0x02
-#define OQO_O2_SMB0_LUMIN_LO 0x20
-#define OQO_O2_SMB0_LUMIN_HI 0x21
-#define OQO_O2_SMB0_BL_LO 0x26
-#define OQO_O2_SMB0_BL_HI 0x27
-#define OQO_O2_SMB0_ACCEL_POLL_ITVL 0x45
-#define OQO_O2_SMB0_ACCEL_XLO 0x50
-#define OQO_O2_SMB0_ACCEL_XHI 0x51
-#define OQO_O2_SMB0_ACCEL_YLO 0x52
-#define OQO_O2_SMB0_ACCEL_YHI 0x53
-#define OQO_O2_SMB0_ACCEL_ZLO 0x54
-#define OQO_O2_SMB0_ACCEL_ZHI 0x55
-/* These may be handled by ACPI not sure yet. */
-#define OQO_O2_SMB0_LID_WAKES_ADDR 0x58
-#define OQO_O2_SMB0_LID_WAKES_MASK 0x08
-
-#define OQO_O2_SMB0_SERIAL_START 0x70
-#define OQO_O2_SMB0_SERIAL_LEN 11
-
-static char oqo_sn[OQO_O2_SMB0_SERIAL_LEN + 1];
-
-/* Other addresses I have noticed used on the 02 SMBUS (from DSDT and whatnot)
- *
- * These are not used because the linux ACPI drivers work fine on them
- *
- * 0x0A -- processor sleep mode?
- * 0x0C -- ACPI events, probably clears when read.
- * 0x30 -- thermal zone
- * There is something going on at 0x31 through 0x34 which is likely
- * also thermal. The values change over time. Have not figured that
- * out yet.
- * 0x41 -- AC detect
- * 0x42 -- LID button ACTUALLY THIS DOES NOT WORK AND NEEDS TO BE FIXED
- * 0xa0 and 0xa1 -- battery something (presence? state?)
- * 0xa4 to 0xcf -- battery info (0xc8-0xca contains "OQO")
- * 0xd4 to 0xef -- other battery stats
- */
-
-/*
- * OQO method GUIDs
- */
-#define OQO_O2_AMW0_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000"
-MODULE_ALIAS("wmi:ABBC0F6D-8EA1-11D1-00A0-C90629100000");
-
-/*
- * Interface type flags
- */
-enum interface_type {
- OQO_O2_AMW0,
-};
-
-/* Each low-level interface must define at least some of the following */
-struct wmi_interface {
- /* The WMI device type */
- u32 type;
-};
-
-static struct wmi_interface AMW0_interface = {
- .type = OQO_O2_AMW0,
-};
-
-/* The detected/chosen interface */
-static struct wmi_interface *interface;
-
-static int dmi_matched(const struct dmi_system_id *dmi)
-{
- model = dmi->driver_data;
- /*
- * Detect which ACPI-WMI interface we're using.
- */
- if (wmi_has_guid(OQO_O2_AMW0_GUID))
- interface = &AMW0_interface;
-
- return 0;
-}
-
-static struct dmi_system_id oqo_dmis[] = {
- {
- .callback = dmi_matched,
- .ident = "OQO 02",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "OQO Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "OQO Model 2"),
- },
- .driver_data = oqo_models + 0,
- },
- {}
-};
-
-/*
- * AMW0 (V1) interface on OQO Model 2
- *
- * wmba: has four functions selected by int arg 1. arg2 is 3 byte buffer.
- * 1: performs GETB method on the SMBUS using bytes 0, 1 of Arg2
- * returns a buffer object containing a single byte
- * 2: performs SETB on SMBUS using bytes 0, 1, 2 of Arg2
- * returns 0 as int.
- * 3: dumps 256 values into a given SMBUS register (not used here)
- * returns 0 as int.
- * 4: puts byte 0 of arg2 into some sort of busy flag. Some ACPI
- * funcs check this (==0) to decide if SMBUS operations are safe.
- * returns 0 as int.
- * wmbb: simply returns the busy flag set by wmba #4
- */
-static acpi_status oqo_smbus_getb(u8 addr, u8 *result)
-{
- struct acpi_buffer input, res;
- acpi_status status;
- union acpi_object *obj;
- u32 arg2;
-
- input.length = 4;
- input.pointer = &arg2;
- res.length = ACPI_ALLOCATE_BUFFER;
- res.pointer = NULL;
-
- arg2 = addr;
- arg2 <<= 8;
- arg2 |= 0x12; /* HOSTCMD */
-
- status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 1, &input, &res);
-
- if (status != AE_OK)
- return status;
-
- obj = (union acpi_object *)res.pointer;
- if (!obj)
- return AE_NULL_OBJECT;
-
- if (obj->type != ACPI_TYPE_BUFFER
- || obj->buffer.length != 1 || obj->buffer.pointer == NULL) {
- kfree(obj);
- return AE_TYPE;
- }
- *result = ((u8 *) (obj->buffer.pointer))[0];
- kfree(obj);
- return status;
-}
-
-static acpi_status oqo_smbus_setb(u8 addr, u8 val)
-{
- struct acpi_buffer input, res;
- acpi_status status;
- union acpi_object *obj;
- u32 arg2;
-
- input.length = 4;
- input.pointer = &arg2;
- res.length = ACPI_ALLOCATE_BUFFER;
- res.pointer = NULL;
-
- arg2 = val;
- arg2 <<= 8;
- arg2 |= addr;
- arg2 <<= 8;
- arg2 |= 0x12; /* HOSTCMD */
-
- status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 2, &input, &res);
-
- if (status != AE_OK)
- return status;
-
- obj = (union acpi_object *)res.pointer;
- if (!obj)
- return AE_NULL_OBJECT;
-
- if (obj->type != ACPI_TYPE_INTEGER) {
- kfree(obj);
- return AE_TYPE;
- }
- kfree(obj);
- return status;
-}
-
-/*
- * We assume we are the only one using this ...ahem... "lock" on
- * the SMBUS because it would be pathetically noneffective otherwise.
- *
- * Nonzero silly_lock will keep certain ACPI routines away from the
- * SMBUS (if they aren't already on it when you call it.) Zero
- * silly_lock will let them back on
- *
- * This is probably useful before sleeping the system, and one
- * waits until any ACPI funcs would have long finished before
- * proceeding. It seems harmless enough and will work to wrap
- * more accesses with it.
- */
-static acpi_status oqo_lock_smbus(int silly_lock)
-{
- struct acpi_buffer input, res;
- acpi_status status;
- union acpi_object *obj;
- u32 arg2;
-
- input.length = 4;
- input.pointer = &arg2;
- res.length = ACPI_ALLOCATE_BUFFER;
- res.pointer = NULL;
-
- arg2 = !!silly_lock;
-
- status = wmi_evaluate_method(OQO_O2_AMW0_GUID, 1, 4, &input, &res);
-
- if (status != AE_OK)
- return status;
-
- obj = (union acpi_object *)res.pointer;
- if (!obj)
- return AE_NULL_OBJECT;
-
- if (obj->type != ACPI_TYPE_INTEGER) {
- kfree(obj);
- return AE_TYPE;
- }
- kfree(obj);
- return status;
-}
-
-static int smread_s16(u8 hi_addr, u8 lo_addr)
-{
- s16 ret = -1;
- acpi_status status;
- u8 r;
-
- /* Keep some ACPI routines off the SMBUS */
- status = oqo_lock_smbus(1);
- if (ACPI_FAILURE(status))
- goto skip;
-
- status = oqo_smbus_getb(hi_addr, &r);
- if (ACPI_FAILURE(status))
- goto skip;
-
- ret = r;
- ret <<= 8;
-
- status = oqo_smbus_getb(lo_addr, &r);
- if (ACPI_FAILURE(status)) {
- ret = -1;
- goto skip;
- }
-
- ret |= r;
- ret &= 0x7fff;
-skip:
- /* Let ACPI routines back on the SMBUS */
- status = oqo_lock_smbus(0);
- if (ACPI_FAILURE(status))
- return -1;
- return (int)ret;
-}
-
-static int smwrite_s16(u8 hi_addr, u8 lo_addr, s16 val)
-{
- acpi_status status;
- u8 r;
- int ret = -1;
-
- status = oqo_lock_smbus(1);
- if (ACPI_FAILURE(status))
- goto skip;
-
- r = (val >> 8) & 0x7f;
- status = oqo_smbus_setb(hi_addr, r);
- if (ACPI_FAILURE(status))
- goto skip;
-
- r = val & 0xff;
- status = oqo_smbus_setb(lo_addr, r);
- if (ACPI_FAILURE(status))
- goto skip;
-
- ret = 0;
-skip:
- status = oqo_lock_smbus(0);
- if (ACPI_FAILURE(status))
- return -1;
- return ret;
-}
-
-static int smread_u8(u8 addr)
-{
- int ret = -1;
- acpi_status status;
- u8 r;
-
- status = oqo_lock_smbus(1);
- if (ACPI_FAILURE(status))
- goto skip;
-
- status = oqo_smbus_getb(addr, &r);
- if (ACPI_FAILURE(status))
- goto skip;
-
- ret = r;
-skip:
- status = oqo_lock_smbus(0);
- if (ACPI_FAILURE(status))
- return -1;
- return (int)ret;
-}
-
-static int smwrite_u8(u8 addr, u8 val)
-{
- acpi_status status;
- int ret = -1;
-
- status = oqo_lock_smbus(1);
- if (ACPI_FAILURE(status))
- goto skip;
-
- status = oqo_smbus_setb(addr, val);
- if (ACPI_FAILURE(status))
- goto skip;
-
- ret = 0;
-skip:
- status = oqo_lock_smbus(0);
- if (ACPI_FAILURE(status))
- return -1;
- return ret;
-}
-
-/*
- * Accelerometer inputdev
- */
-
-/*
- * Get a reading of the accelerometer from the firwmware and push
- * it to an inputdev.
- *
- * Also the ambient light detector hitch-hikes on the inputdev, since
- * it could be useful in some of the same applications for accelerometers.
- *
- * Available information and a bit of poking have not found a
- * way to freeze a snapshot of the accelerometer data, so we have
- * to do consistency checks to reduce the odds that we mix low
- * and high bytes from different updates.
- *
- * Unfortunately SMBUS access is very slow (11ms) and the firmware API
- * does not provide 2-byte transfers, so mixed readings happen and
- * have to be corrected a lot. (Do not know why; it should be a
- * multi-kHz.. bus and the reads take only a hundred-ish cycles/byte.
- * It is not the ACPI function -- it is slow on i2c-viapro as well.)
- *
- * Since there is such a big time lag between readings, the axis
- * are decoupled and reported separately on different timelines as
- * different events rather than as a set.
- */
-static acpi_status oqo_read_kine(int *good, s16 *x, s16 *y, s16 *z,
- u16 *lumin)
-{
- u8 hiregs[4] = { OQO_O2_SMB0_ACCEL_XHI,
- OQO_O2_SMB0_ACCEL_YHI,
- OQO_O2_SMB0_ACCEL_ZHI,
- OQO_O2_SMB0_LUMIN_HI
- };
- u8 loregs[4] = { OQO_O2_SMB0_ACCEL_XLO,
- OQO_O2_SMB0_ACCEL_YLO,
- OQO_O2_SMB0_ACCEL_ZLO,
- OQO_O2_SMB0_LUMIN_LO
- };
-
- short ax[4] = { ABS_X, ABS_Y, ABS_Z, ABS_MISC };
- u8 realgood = 0;
- u16 res[4];
- acpi_status status;
- int i;
-
- *good = 0;
-
- /* Routine: Starting with the lo byte, read lo/hi bytes
- alternately until two lo byte readings, match. Then
- take that reading and combine it with the hi reading
- sandwiched between. Errors can still happen when
- jittering at wrap boundaries, but should be rare.
-
- Don't use this for missile guidance.
-
- Userspace post-processing error detection encouraged.
- */
- for (i = 0; i < 4; i++) {
- int maxtry;
- u32 log;
- u8 r, lo, hi;
-
- lo = loregs[i];
- hi = hiregs[i];
- log = 0;
-
-#define LOGRES(reg) do { \
- status = oqo_smbus_getb(reg, &r); \
- log <<= 8; log |= r; log &= 0xffffff; \
- if (ACPI_FAILURE(status)) \
- goto leave; \
- } while (0)
-
- maxtry = OQO_KINE_MAXTRY + 1;
- while (maxtry) {
- LOGRES(lo);
- if (maxtry <= OQO_KINE_MAXTRY &&
- (log >> 16) == (log & 0xff)) {
- *(res + i) = log & 0xffff;
- break;
- }
- LOGRES(hi);
- maxtry--;
- }
-
- if (maxtry == OQO_KINE_MAXTRY)
- realgood |= 1 << i;
-
- if (maxtry) {
- *good |= 1 << i;
- /* JIC CYA: this bit may be reserved */
- res[3] &= 0x7fff;
- input_report_abs(oqo_kine, ax[i], (s16) res[i]);
- }
- /* else we had trouble getting the reading to lock
- and we skip reporting this axis.
- */
- }
-
- *x = (u16) res[0];
- *y = (u16) res[1];
- *z = (u16) res[2];
- *lumin = (u16) res[3];
- return status;
-leave:
- return status;
-}
-
-/*
- * Generic Device (interface-independent)
- */
-
-static void oqo_kine_poll(struct input_polled_dev *dev)
-{
- s16 x, y, z;
- u16 lumin;
- int good;
- /* struct timeval tv1, tv2; */
-
- if (dev != oqo_kine_polled)
- return;
- if (orig.kine_itvl < 0)
- return;
-
- x = y = z = 0;
- oqo_read_kine(&good, &x, &y, &z, &lumin);
-}
-
-static int __devinit oqo_kine_init(void)
-{
- int err;
-
- oqo_kine = input_allocate_device();
- if (!oqo_kine)
- return -ENOMEM;
-
- oqo_kine->name = "OQO embedded accelerometer";
- oqo_kine->phys = "platform:oqo-wmi:kine";
- oqo_kine->id.bustype = 0;
- oqo_kine->id.vendor = 0;
- oqo_kine->id.product = 2;
- oqo_kine->id.version = 0;
- oqo_kine->evbit[0] = BIT_MASK(EV_ABS);
- set_bit(ABS_X, oqo_kine->absbit);
- set_bit(ABS_Y, oqo_kine->absbit);
- set_bit(ABS_Z, oqo_kine->absbit);
- set_bit(ABS_MISC, oqo_kine->absbit);
- oqo_kine->absmin[ABS_X] =
- oqo_kine->absmin[ABS_Y] =
- oqo_kine->absmin[ABS_Z] = oqo_kine->absmin[ABS_MISC] = -32768;
- oqo_kine->absmax[ABS_X] =
- oqo_kine->absmax[ABS_Y] =
- oqo_kine->absmax[ABS_Z] = oqo_kine->absmax[ABS_MISC] = 32767;
-
- dev_set_name(&oqo_kine->dev, "kine");
-
- oqo_kine_polled = input_allocate_polled_device();
- if (!oqo_kine_polled) {
- err = -ENOMEM;
- goto bail0;
- }
-
- oqo_kine_polled->poll = oqo_kine_poll;
- oqo_kine_polled->poll_interval = 250;
- oqo_kine_polled->input = oqo_kine;
-
- orig.kine_itvl = -1; /* prevent callback from running */
- err = input_register_polled_device(oqo_kine_polled);
- if (err) {
- printk(OQO_ERR "Failed to register OQO kine input\n");
- goto bail1;
- }
-
- /* This will allow the callback to run now if successful. */
- orig.kine_itvl = smread_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL);
- smwrite_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL, 250);
- curr.kine_itvl = smread_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL);
- if (orig.kine_itvl < 0 || curr.kine_itvl != 250) {
- printk(OQO_ERR "Test communication with kine sensor failed\n");
- err = -ENODEV;
- goto bail2;
- }
-
- printk(OQO_INFO "Created OQO kine input.\n");
- printk(OQO_INFO "Firmware interval %ims, driver interval %ims\n",
- curr.kine_itvl, oqo_kine_polled->poll_interval);
- return 0;
-bail2:
- input_unregister_polled_device(oqo_kine_polled);
-bail1:
- input_free_polled_device(oqo_kine_polled); /* frees oqo_kine */
- return err;
-bail0:
- input_free_device(oqo_kine);
- return err;
-}
-
-static void __devexit oqo_kine_fini(void)
-{
- smwrite_u8(OQO_O2_SMB0_ACCEL_POLL_ITVL, orig.kine_itvl);
- input_unregister_polled_device(oqo_kine_polled);
- input_free_polled_device(oqo_kine_polled);
-}
-
-/*
- * Backlight device
- */
-static int read_brightness(struct backlight_device *bd)
-{
- return (int)smread_s16(OQO_O2_SMB0_BL_HI, OQO_O2_SMB0_BL_LO);
-}
-
-static int update_bl_status(struct backlight_device *bd)
-{
- return smwrite_s16(OQO_O2_SMB0_BL_HI,
- OQO_O2_SMB0_BL_LO, (s16) bd->props.brightness);
-}
-
-static struct backlight_ops oqo_bl_ops = {
- .get_brightness = read_brightness,
- .update_status = update_bl_status,
-};
-
-static int __devinit oqo_backlight_init(struct device *dev)
-{
- struct backlight_device *bd;
-
- /*
- * It would be nice if someone would figure out how backlights
- * like these, which are not driven through the video hardware,
- * are supposed to find their associated fb and bind to it (and
- * rebind when fb drivers change.
- *
- * Most extras backlights just shove a junk name in like we do here,
- * and don't end up integrated with fbcon sysfs as a result.
- */
- bd = backlight_device_register("oqo-bl", dev, NULL, &oqo_bl_ops);
-
- if (IS_ERR(bd)) {
- printk(OQO_ERR "Could not register OQO backlight device\n");
- oqo_backlight_device = NULL;
- return PTR_ERR(bd);
- }
-
- oqo_backlight_device = bd;
- bd->props.max_brightness = 0x7fff;
- curr.bl_bright = orig.bl_bright = bd->props.brightness =
- read_brightness(NULL);
-
- if (bd->props.brightness < 0)
- goto fail;
-
- backlight_update_status(bd);
- printk(OQO_INFO "Found backlight set at %i\n", bd->props.brightness);
- return 0;
-
-fail:
- backlight_device_unregister(oqo_backlight_device);
- oqo_backlight_device = NULL;
- return -ENODEV;
-}
-
-static void __devexit oqo_backlight_fini(void)
-{
- if (!oqo_backlight_device)
- return;
- oqo_backlight_device->props.brightness = orig.bl_bright;
- backlight_update_status(oqo_backlight_device);
- backlight_device_unregister(oqo_backlight_device);
-}
-
-/*
- * RFKill device
- */
-
-static int oqo_rfkill_get(void *data, enum rfkill_state *state)
-{
- int res;
-
- res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
- if (res < 0)
- return res;
-
- res &= OQO_O2_SMB0_WWAN_DSBL_MASK;
-
- if (res)
- *state = RFKILL_STATE_SOFT_BLOCKED;
- else
- *state = RFKILL_STATE_UNBLOCKED;
-
- return 0;
-}
-
-static int oqo_rfkill_toggle(void *data, enum rfkill_state state)
-{
- int res;
-
- res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
-
- if (state == RFKILL_STATE_UNBLOCKED)
- res &= ~OQO_O2_SMB0_WWAN_DSBL_MASK;
- else
- res |= OQO_O2_SMB0_WWAN_DSBL_MASK;
-
- return smwrite_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR, res);
-}
-
-static int __devinit oqo_rfkill_init(struct device *dev)
-{
- int res;
-
- oqo_rfkill = rfkill_allocate(dev, RFKILL_TYPE_WWAN);
- if (!oqo_rfkill)
- return -ENODEV;
-
- res = smread_u8(OQO_O2_SMB0_WWAN_DSBL_ADDR);
- res &= OQO_O2_SMB0_WWAN_DSBL_MASK;
-
- oqo_rfkill->name = "oqo-wwan";
- if (res)
- oqo_rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
- else
- oqo_rfkill->state = RFKILL_STATE_UNBLOCKED;
-
- oqo_rfkill->get_state = oqo_rfkill_get;
- oqo_rfkill->toggle_radio = oqo_rfkill_toggle;
- oqo_rfkill->user_claim_unsupported = 1;
-
- res = rfkill_register(oqo_rfkill);
-
- if (res)
- rfkill_free(oqo_rfkill);
-
- return res;
-}
-
-static void __devexit oqo_rfkill_fini(void)
-{
- if (!oqo_rfkill)
- return;
- rfkill_unregister(oqo_rfkill);
-}
-
-/*
- * Platform device
- */
-
-static int __devinit oqo_platform_probe(struct platform_device *device)
-{
- int err;
- int i;
- char *troubleok = "trouble, but continuing.\n";
-
- memset(oqo_sn, 0, OQO_O2_SMB0_SERIAL_LEN + 1);
- for (i = 0; i < OQO_O2_SMB0_SERIAL_LEN; i++) {
- err = oqo_smbus_getb(OQO_O2_SMB0_SERIAL_START + i, oqo_sn + i);
- if (err) {
- printk(OQO_ERR "Serial number check failed.\n");
- return err;
- }
- }
- printk(OQO_INFO "Found OQO with serial number %s.\n", oqo_sn);
-
- err = oqo_backlight_init(&device->dev);
- if (err)
- printk(OQO_ERR "Backlight init %s", troubleok);
-
- err = oqo_rfkill_init(&device->dev);
- if (err)
- printk(OQO_ERR "RFKill init %s", troubleok);
-
- /* LID does not work at all yet, and this may be taken
- care of by ACPI.
- */
- orig.lid_wakes = smread_u8(OQO_O2_SMB0_LID_WAKES_ADDR);
- orig.lid_wakes &= OQO_O2_SMB0_LID_WAKES_MASK;
- orig.lid_wakes = curr.lid_wakes = !!orig.lid_wakes;
- if (orig.lid_wakes < 0) {
- printk(OQO_ERR "Wake on LID event %s", troubleok);
- } else {
- printk(OQO_INFO "Wake on LID is %s.\n",
- (orig.lid_wakes ? "on" : "off"));
- }
-
- err = oqo_kine_init();
- return err;
-}
-
-static int oqo_platform_remove(struct platform_device *device)
-{
- oqo_backlight_fini();
- oqo_rfkill_fini();
- oqo_kine_fini();
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int oqo_platform_suspend(struct platform_device *dev, pm_message_t state)
-{
- if (!interface)
- return -ENOMEM;
-
- /* This sticks during boot so do not turn it entirely off */
- if (oqo_backlight_device) {
- curr.bl_bright = read_brightness(oqo_backlight_device);
- smwrite_s16(OQO_O2_SMB0_BL_HI, OQO_O2_SMB0_BL_LO, 256);
- }
- return 0;
-}
-
-static int oqo_platform_resume(struct platform_device *device)
-{
- if (!interface)
- return -ENOMEM;
-
- if (oqo_backlight_device) {
- smwrite_s16(OQO_O2_SMB0_BL_HI,
- OQO_O2_SMB0_BL_LO, curr.bl_bright);
- }
-
- return 0;
-}
-
-#else
-#define oqo_platform_suspend NULL
-#define oqo_platform_resume NULL
-#endif
-
-static struct platform_driver oqo_platform_driver = {
- .driver = {
- .name = "oqo-wmi",
- .owner = THIS_MODULE,
- },
- .probe = oqo_platform_probe,
- .remove = oqo_platform_remove,
- .suspend = oqo_platform_suspend,
- .resume = oqo_platform_resume,
-};
-
-static int __init oqo_wmi_init(void)
-{
- int err;
-
- dmi_check_system(oqo_dmis);
-
- if (!interface && force) {
- model = oqo_models;
- if (wmi_has_guid(OQO_O2_AMW0_GUID))
- interface = &AMW0_interface;
- }
-
- if (!interface) {
- printk(OQO_ERR "No or unsupported WMI interface. Aborting.\n");
- printk(OQO_ERR "Hint: Get dmidecode working and try again.\n");
- printk(OQO_ERR "(Check \"System Management BIOS\" in BIOS)\n");
- if (!force)
- printk(OQO_ERR "Use the force option to skip DMI"
- " checking\n");
- return -ENODEV;
- }
-
- err = platform_driver_register(&oqo_platform_driver);
- if (err) {
- printk(OQO_ERR "platform_driver_register gave %d.\n", err);
- goto bail0;
- }
-
- oqo_platform_device = platform_device_alloc("oqo-wmi", -1);
- if (!oqo_platform_device) {
- printk(OQO_ERR "Could not allocate platform device.\n");
- err = -ENOMEM;
- goto bail1;
- }
-
- err = platform_device_add(oqo_platform_device);
- if (err) {
- printk(OQO_ERR "platform_device_add gave %d.\n", err);
- platform_device_put(oqo_platform_device);
- goto bail1;
- }
-
- return 0;
-
-bail1:
- platform_driver_unregister(&oqo_platform_driver);
-bail0:
- return err;
-}
-
-static void __exit oqo_wmi_fini(void)
-{
- platform_device_del(oqo_platform_device);
- platform_driver_unregister(&oqo_platform_driver);
-
- return;
-}
-
-module_init(oqo_wmi_init);
-module_exit(oqo_wmi_fini);