提交 6b06d2cc 编写于 作者: L Linus Torvalds

Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (105 commits)
  sonypi: use mutex instead of semaphore
  sony-laptop: remove user visible camera controls as platform attributes
  meye: make meye use sony-laptop instead of sonypi
  sony-laptop: add a meye-usable include file for camera ops
  sony-laptop: complete the motion eye camera support in sony-laptop
  sonypi: try to detect if sony-laptop has already taken one of the known ioports
  sonypi: suggest sonypi users to try sony-laptop instead
  sony-laptop: add edge modem support (also called WWAN)
  sony-laptop: add locking on accesses to the ioport and global vars
  sony-laptop: add camera enable/disable parameter, better handle possible infinite loop
  thinkpad-acpi: make drivers/misc/thinkpad_acpi:fan_mutex static
  ACPI: thinkpad-acpi: add sysfs support to wan and bluetooth subdrivers
  ACPI: thinkpad-acpi: add sysfs support to hotkey subdriver
  ACPI: thinkpad-acpi: improve dock subdriver initialization
  ACPI: thinkpad-acpi: improve debugging for acpi helpers
  ACPI: thinkpad-acpi: improve fan control documentation
  ACPI: thinkpad-acpi: map ENXIO to EINVAL for fan sysfs
  ACPI: thinkpad-acpi: fix a fan watchdog invocation
  ACPI: thinkpad-acpi: do not arm fan watchdog if it would not work
  ACPI: thinkpad-acpi: add a fan-control feature master toggle
  ...
......@@ -181,19 +181,41 @@ and is between 256 and 4096 characters. It is defined in the file
that require a timer override, but don't have
HPET
acpi_dbg_layer= [HW,ACPI]
acpi.debug_layer= [HW,ACPI]
Format: <int>
Each bit of the <int> indicates an ACPI debug layer,
1: enable, 0: disable. It is useful for boot time
debugging. After system has booted up, it can be set
via /proc/acpi/debug_layer.
acpi_dbg_level= [HW,ACPI]
via /sys/module/acpi/parameters/debug_layer.
CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
Available bits (add the numbers together) to enable debug output
for specific parts of the ACPI subsystem:
0x01 utilities 0x02 hardware 0x04 events 0x08 tables
0x10 namespace 0x20 parser 0x40 dispatcher
0x80 executer 0x100 resources 0x200 acpica debugger
0x400 os services 0x800 acpica disassembler.
The number can be in decimal or prefixed with 0x in hex.
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
acpi.debug_level= [HW,ACPI]
Format: <int>
Each bit of the <int> indicates an ACPI debug level,
1: enable, 0: disable. It is useful for boot time
debugging. After system has booted up, it can be set
via /proc/acpi/debug_level.
via /sys/module/acpi/parameters/debug_level.
CONFIG_ACPI_DEBUG must be enabled for this to produce any output.
Available bits (add the numbers together) to enable different
debug output levels of the ACPI subsystem:
0x01 error 0x02 warn 0x04 init 0x08 debug object
0x10 info 0x20 init names 0x40 parse 0x80 load
0x100 dispatch 0x200 execute 0x400 names 0x800 operation region
0x1000 bfield 0x2000 tables 0x4000 values 0x8000 objects
0x10000 resources 0x20000 user requests 0x40000 package.
The number can be in decimal or prefixed with 0x in hex.
Warning: Many of these options can produce a lot of
output and make your system unusable. Be very careful.
acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT
......
......@@ -3,12 +3,18 @@ Sony Notebook Control Driver (SNC) Readme
Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
This mini-driver drives the SNC device present in the ACPI BIOS of
the Sony Vaio laptops.
This mini-driver drives the SNC and SPIC device present in the ACPI BIOS of the
Sony Vaio laptops. This driver mixes both devices functions under the same
(hopefully consistent) interface. This also means that the sonypi driver is
obsoleted by sony-laptop now.
It gives access to some extra laptop functionalities. In its current
form, this driver let the user set or query the screen brightness
through the backlight subsystem and remove/apply power to some devices.
Fn keys (hotkeys):
------------------
Some models report hotkeys through the SNC or SPIC devices, such events are
reported both through the ACPI subsystem as acpi events and through the INPUT
subsystem. See the logs of acpid or /proc/acpi/event and
/proc/bus/input/devices to find out what those events are and which input
devices are created by the driver.
Backlight control:
------------------
......@@ -39,6 +45,8 @@ The files are:
audiopower power on/off the internal sound card
lanpower power on/off the internal ethernet card
(only in debug mode)
bluetoothpower power on/off the internal bluetooth device
fanspeed get/set the fan speed
Note that some files may be missing if they are not supported
by your particular laptop model.
......@@ -76,9 +84,9 @@ The sony-laptop driver creates, for some of those methods (the most
current ones found on several Vaio models), an entry under
/sys/devices/platform/sony-laptop, just like the 'cdpower' one.
You can create other entries corresponding to your own laptop methods by
further editing the source (see the 'sony_acpi_values' table, and add a new
further editing the source (see the 'sony_nc_values' table, and add a new
entry to this table with your get/set method names using the
HANDLE_NAMES macro).
SNC_HANDLE_NAMES macro).
Your mission, should you accept it, is to try finding out what
those entries are for, by reading/writing random values from/to those
......@@ -87,6 +95,9 @@ files and find out what is the impact on your laptop.
Should you find anything interesting, please report it back to me,
I will not disavow all knowledge of your actions :)
See also http://www.linux.it/~malattia/wiki/index.php/Sony_drivers for other
useful info.
Bugs/Limitations:
-----------------
......
......@@ -5,10 +5,9 @@ Vaio Picturebook Motion Eye Camera Driver Readme
Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
This driver enable the use of video4linux compatible applications with the
Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O
Control Device" driver (which can be found in the "Character drivers"
section of the kernel configuration utility) to be compiled and installed
(using its "camera=1" parameter).
Motion Eye camera. This driver requires the "Sony Laptop Extras" driver (which
can be found in the "Misc devices" section of the kernel configuration utility)
to be compiled and installed (using its "camera=1" parameter).
It can do at maximum 30 fps @ 320x240 or 15 fps @ 640x480.
......
......@@ -1658,15 +1658,6 @@ W: http://www.ia64-linux.org/
T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
S: Maintained
IBM ACPI EXTRAS DRIVER
P: Henrique de Moraes Holschuh
M: ibm-acpi@hmh.eng.br
L: ibm-acpi-devel@lists.sourceforge.net
W: http://ibm-acpi.sourceforge.net
W: http://thinkwiki.org/wiki/Ibm-acpi
T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
S: Maintained
SN-IA64 (Itanium) SUB-PLATFORM
P: Jes Sorensen
M: jes@sgi.com
......@@ -3166,6 +3157,15 @@ P: Chris Zankel
M: chris@zankel.net
S: Maintained
THINKPAD ACPI EXTRAS DRIVER
P: Henrique de Moraes Holschuh
M: ibm-acpi@hmh.eng.br
L: ibm-acpi-devel@lists.sourceforge.net
W: http://ibm-acpi.sourceforge.net
W: http://thinkwiki.org/wiki/Ibm-acpi
T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
S: Maintained
UltraSPARC (sparc64):
P: David S. Miller
M: davem@davemloft.net
......
......@@ -23,10 +23,13 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header)
static int __init check_bridge(int vendor, int device)
{
#ifdef CONFIG_ACPI
static int warned;
/* According to Nvidia all timer overrides are bogus unless HPET
is enabled. */
if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) {
if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) {
if (!warned && acpi_table_parse(ACPI_SIG_HPET,
nvidia_hpet_check)) {
warned = 1;
acpi_skip_timer_override = 1;
printk(KERN_INFO "Nvidia board "
"detected. Ignoring ACPI "
......
......@@ -85,8 +85,8 @@ config ACPI_PROCFS
depends on ACPI
default y
---help---
Procfs interface for ACPI is made optional for back-compatible.
As the same functions are duplicated in sysfs interface
The Procfs interface for ACPI is made optional for backward compatibility.
As the same functions are duplicated in the sysfs interface
and this proc interface will be removed some time later,
it's marked as deprecated.
( /proc/acpi/debug_layer && debug_level are deprecated by
......@@ -218,43 +218,6 @@ config ACPI_ASUS
NOTE: This driver is deprecated and will probably be removed soon,
use asus-laptop instead.
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
select BACKLIGHT_CLASS_DEVICE
---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
output switching, ThinkLight control, UltraBay eject and more.
For more information about this driver see <file:Documentation/ibm-acpi.txt>
and <http://ibm-acpi.sf.net/> .
If you have an IBM ThinkPad laptop, say Y or M here.
config ACPI_IBM_DOCK
bool "Legacy Docking Station Support"
depends on ACPI_IBM
depends on ACPI_DOCK=n
default n
---help---
Allows the ibm_acpi driver to handle docking station events.
This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will
allow locking and removing the laptop from the docking station,
but will not properly connect PCI devices.
If you are not sure, say N here.
config ACPI_IBM_BAY
bool "Legacy Removable Bay Support"
depends on ACPI_IBM
default y
---help---
Allows the ibm_acpi driver to handle removable bays. It will allow
disabling the device in the bay, and also generate notifications when
the bay lever is ejected or inserted.
If you are not sure, say Y here.
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
......@@ -388,11 +351,10 @@ config ACPI_HOTPLUG_MEMORY
config ACPI_SBS
tristate "Smart Battery System (EXPERIMENTAL)"
depends on X86 && I2C
depends on X86
depends on EXPERIMENTAL
help
This driver adds support for the Smart Battery System.
Depends on I2C (Device Drivers ---> I2C support)
A "Smart Battery" is quite old and quite rare compared
to today's ACPI "Control Method" battery.
......
#
# Makefile for the Linux ACPI interpreter
#
#
export ACPI_CFLAGS
......@@ -32,16 +32,17 @@ obj-y += osl.o utils.o \
processor-objs += processor_core.o processor_throttling.o \
processor_idle.o processor_thermal.o
ifdef CONFIG_CPU_FREQ
processor-objs += processor_perflib.o
processor-objs += processor_perflib.o
endif
obj-y += sleep/
obj-y += bus.o glue.o
obj-y += scan.o
# Keep EC driver first. Initialization of others depend on it.
obj-$(CONFIG_ACPI_EC) += ec.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
obj-$(CONFIG_ACPI_EC) += ec.o
obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_DOCK) += dock.o
obj-$(CONFIG_ACPI_BAY) += bay.o
......@@ -55,8 +56,7 @@ obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
......@@ -44,11 +44,6 @@ MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
MODULE_DESCRIPTION("Hotplug Mem Driver");
MODULE_LICENSE("GPL");
/* ACPI _STA method values */
#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
/* Memory Device States */
#define MEMORY_INVALID_STATE 0
#define MEMORY_POWER_ON_STATE 1
......@@ -204,9 +199,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
* Check for device status. Device should be
* present/enabled/functioning.
*/
if (!((current_status & ACPI_MEMORY_STA_PRESENT)
&& (current_status & ACPI_MEMORY_STA_ENABLED)
&& (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
if (!((current_status & ACPI_STA_DEVICE_PRESENT)
&& (current_status & ACPI_STA_DEVICE_ENABLED)
&& (current_status & ACPI_STA_DEVICE_FUNCTIONING)))
return -ENODEV;
return 0;
......@@ -286,7 +281,7 @@ static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
return -ENODEV;
/* Check for device status. Device should be disabled */
if (current_status & ACPI_MEMORY_STA_ENABLED)
if (current_status & ACPI_STA_DEVICE_ENABLED)
return -EINVAL;
return 0;
......
......@@ -103,7 +103,9 @@ int acpi_bus_get_status(struct acpi_device *device)
else if (device->parent)
device->status = device->parent->status;
else
STRUCT_TO_INT(device->status) = 0x0F;
STRUCT_TO_INT(device->status) =
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
if (device->status.functional && !device->status.present) {
printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
......
......@@ -49,8 +49,6 @@ MODULE_AUTHOR("Anil S Keshavamurthy");
MODULE_DESCRIPTION("ACPI container driver");
MODULE_LICENSE("GPL");
#define ACPI_STA_PRESENT (0x00000001)
static int acpi_container_add(struct acpi_device *device);
static int acpi_container_remove(struct acpi_device *device, int type);
......@@ -75,13 +73,13 @@ static int is_device_present(acpi_handle handle)
status = acpi_get_handle(handle, "_STA", &temp);
if (ACPI_FAILURE(status))
return 1; /* _STA not found, assmue device present */
return 1; /* _STA not found, assume device present */
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return 0; /* Firmware error */
return ((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT);
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}
/*******************************************************************/
......
......@@ -29,6 +29,7 @@
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/stddef.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
......@@ -667,6 +668,23 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
}
DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
/*
* show_dock_uid - read method for "uid" file in sysfs
*/
static ssize_t show_dock_uid(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned long lbuf;
acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf);
if(ACPI_FAILURE(status)) {
return 0;
}
return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
}
DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
/**
* dock_add - add a new dock station
* @handle: the dock station handle
......@@ -715,6 +733,13 @@ static int dock_add(acpi_handle handle)
kfree(dock_station);
return ret;
}
ret = device_create_file(&dock_device.dev, &dev_attr_uid);
if (ret) {
printk("Error %d adding sysfs file\n", ret);
platform_device_unregister(&dock_device);
kfree(dock_station);
return ret;
}
/* Find dependent devices */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
......
/*
* acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
* ec.c - ACPI Embedded Controller Driver (v2.0)
*
* Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
......@@ -91,9 +93,9 @@ static struct acpi_driver acpi_ec_driver = {
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
/* External interfaces use first EC only, so remember */
static struct acpi_ec {
acpi_handle handle;
unsigned long uid;
unsigned long gpe;
unsigned long command_addr;
unsigned long data_addr;
......@@ -101,12 +103,8 @@ static struct acpi_ec {
struct mutex lock;
atomic_t query_pending;
atomic_t event_count;
atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t wait;
} *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
} *boot_ec, *first_ec;
/* --------------------------------------------------------------------------
Transaction Management
......@@ -173,56 +171,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
return -ETIME;
}
#ifdef ACPI_FUTURE_USAGE
/*
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
{
u8 tmp = 0;
u8 status = 0;
status = acpi_ec_read_status(ec);
if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
if (status)
goto end;
acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
tmp = acpi_ec_read_data(ec);
if (tmp != 0x90) { /* Burst ACK byte */
return -EINVAL;
}
}
atomic_set(&ec->leaving_burst, 0);
return 0;
end:
ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
return -1;
}
int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
{
u8 status = 0;
status = acpi_ec_read_status(ec);
if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
if (status)
goto end;
acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
}
atomic_set(&ec->leaving_burst, 1);
return 0;
end:
ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
return -1;
}
#endif /* ACPI_FUTURE_USAGE */
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
const u8 * wdata, unsigned wdata_len,
u8 * rdata, unsigned rdata_len)
......@@ -312,6 +260,21 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
return status;
}
/*
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
int acpi_ec_burst_enable(struct acpi_ec *ec)
{
u8 d;
return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1);
}
int acpi_ec_burst_disable(struct acpi_ec *ec)
{
return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0);
}
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
{
int result;
......@@ -333,18 +296,33 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
/*
* Externally callable EC access functions. For now, assume 1 EC only
*/
int ec_burst_enable(void)
{
if (!first_ec)
return -ENODEV;
return acpi_ec_burst_enable(first_ec);
}
EXPORT_SYMBOL(ec_burst_enable);
int ec_burst_disable(void)
{
if (!first_ec)
return -ENODEV;
return acpi_ec_burst_disable(first_ec);
}
EXPORT_SYMBOL(ec_burst_disable);
int ec_read(u8 addr, u8 * val)
{
struct acpi_ec *ec;
int err;
u8 temp_data;
if (!first_ec)
return -ENODEV;
ec = acpi_driver_data(first_ec);
err = acpi_ec_read(ec, addr, &temp_data);
err = acpi_ec_read(first_ec, addr, &temp_data);
if (!err) {
*val = temp_data;
......@@ -357,15 +335,12 @@ EXPORT_SYMBOL(ec_read);
int ec_write(u8 addr, u8 val)
{
struct acpi_ec *ec;
int err;
if (!first_ec)
return -ENODEV;
ec = acpi_driver_data(first_ec);
err = acpi_ec_write(ec, addr, val);
err = acpi_ec_write(first_ec, addr, val);
return err;
}
......@@ -376,14 +351,10 @@ int ec_transaction(u8 command,
const u8 * wdata, unsigned wdata_len,
u8 * rdata, unsigned rdata_len)
{
struct acpi_ec *ec;
if (!first_ec)
return -ENODEV;
ec = acpi_driver_data(first_ec);
return acpi_ec_transaction(ec, command, wdata,
return acpi_ec_transaction(first_ec, command, wdata,
wdata_len, rdata, rdata_len);
}
......@@ -420,7 +391,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
static void acpi_ec_gpe_query(void *ec_cxt)
{
struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
struct acpi_ec *ec = ec_cxt;
u8 value = 0;
char object_name[8];
......@@ -438,8 +409,9 @@ static u32 acpi_ec_gpe_handler(void *data)
{
acpi_status status = AE_OK;
u8 value;
struct acpi_ec *ec = (struct acpi_ec *)data;
struct acpi_ec *ec = data;
atomic_inc(&ec->event_count);
if (acpi_ec_mode == EC_INTR) {
wake_up(&ec->wait);
}
......@@ -482,7 +454,7 @@ acpi_ec_space_handler(u32 function,
void *handler_context, void *region_context)
{
int result = 0;
struct acpi_ec *ec = NULL;
struct acpi_ec *ec = handler_context;
u64 temp = *value;
acpi_integer f_v = 0;
int i = 0;
......@@ -494,8 +466,6 @@ acpi_ec_space_handler(u32 function,
return AE_BAD_PARAMETER;
}
ec = (struct acpi_ec *)handler_context;
next_byte:
switch (function) {
case ACPI_READ:
......@@ -551,18 +521,16 @@ static struct proc_dir_entry *acpi_ec_dir;
static int acpi_ec_read_info(struct seq_file *seq, void *offset)
{
struct acpi_ec *ec = (struct acpi_ec *)seq->private;
struct acpi_ec *ec = seq->private;
if (!ec)
goto end;
seq_printf(seq, "gpe: 0x%02x\n", (u32) ec->gpe);
seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
(u32) ec->command_addr, (u32) ec->data_addr);
seq_printf(seq, "use global lock: %s\n",
seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
(unsigned)ec->command_addr, (unsigned)ec->data_addr);
seq_printf(seq, "use global lock:\t%s\n",
ec->global_lock ? "yes" : "no");
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
end:
return 0;
}
......@@ -619,154 +587,122 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
static acpi_status
ec_parse_io_ports(struct acpi_resource *resource, void *context);
static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
static struct acpi_ec *make_acpi_ec(void)
{
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec)
return NULL;
atomic_set(&ec->query_pending, 1);
atomic_set(&ec->event_count, 1);
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
return ec;
}
static int acpi_ec_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
if (!device)
return -EINVAL;
ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec)
return -ENOMEM;
ec->handle = device->handle;
ec->uid = -1;
mutex_init(&ec->lock);
atomic_set(&ec->query_pending, 0);
atomic_set(&ec->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
atomic_set(&ec->leaving_burst, 1);
init_waitqueue_head(&ec->wait);
}
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
if (ec_ecdt) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler);
acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
&acpi_ec_gpe_handler);
ec = make_acpi_ec();
if (!ec)
return -ENOMEM;
kfree(ec_ecdt);
status = ec_parse_device(device->handle, 0, ec, NULL);
if (status != AE_CTRL_TERMINATE) {
kfree(ec);
return -EINVAL;
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Obtaining GPE bit assignment"));
result = -ENODEV;
goto end;
}
/* Check if we found the boot EC */
if (boot_ec) {
if (boot_ec->gpe == ec->gpe) {
/* We might have incorrect info for GL at boot time */
mutex_lock(&boot_ec->lock);
boot_ec->global_lock = ec->global_lock;
mutex_unlock(&boot_ec->lock);
kfree(ec);
ec = boot_ec;
}
} else
first_ec = ec;
ec->handle = device->handle;
acpi_driver_data(device) = ec;
result = acpi_ec_add_fs(device);
if (result)
goto end;
acpi_ec_add_fs(device);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
acpi_device_name(device), acpi_device_bid(device),
(u32) ec->gpe));
if (!first_ec)
first_ec = device;
end:
if (result)
kfree(ec);
return result;
return 0;
}
static int acpi_ec_remove(struct acpi_device *device, int type)
{
struct acpi_ec *ec = NULL;
struct acpi_ec *ec;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
acpi_ec_remove_fs(device);
acpi_driver_data(device) = NULL;
if (ec == first_ec)
first_ec = NULL;
kfree(ec);
/* Don't touch boot EC */
if (boot_ec != ec)
kfree(ec);
return 0;
}
static acpi_status
acpi_ec_io_ports(struct acpi_resource *resource, void *context)
ec_parse_io_ports(struct acpi_resource *resource, void *context)
{
struct acpi_ec *ec = (struct acpi_ec *)context;
struct acpi_ec *ec = context;
if (resource->type != ACPI_RESOURCE_TYPE_IO) {
if (resource->type != ACPI_RESOURCE_TYPE_IO)
return AE_OK;
}
/*
* The first address region returned is the data port, and
* the second address region returned is the status/command
* port.
*/
if (ec->data_addr == 0) {
if (ec->data_addr == 0)
ec->data_addr = resource->data.io.minimum;
} else if (ec->command_addr == 0) {
else if (ec->command_addr == 0)
ec->command_addr = resource->data.io.minimum;
} else {
else
return AE_CTRL_TERMINATE;
}
return AE_OK;
}
static int acpi_ec_start(struct acpi_device *device)
static int ec_install_handlers(struct acpi_ec *ec)
{
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
/*
* Get I/O port addresses. Convert to GAS format.
*/
status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec);
if (ACPI_FAILURE(status) || ec->command_addr == 0) {
ACPI_EXCEPTION((AE_INFO, status,
"Error getting I/O port addresses"));
return -ENODEV;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
ec->gpe, ec->command_addr, ec->data_addr));
/*
* Install GPE handler
*/
acpi_status status;
status = acpi_install_gpe_handler(NULL, ec->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
if (ACPI_FAILURE(status))
return -ENODEV;
}
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
......@@ -779,18 +715,49 @@ static int acpi_ec_start(struct acpi_device *device)
return -ENODEV;
}
return AE_OK;
/* EC is fully operational, allow queries */
atomic_set(&ec->query_pending, 0);
return 0;
}
static int acpi_ec_start(struct acpi_device *device)
{
struct acpi_ec *ec;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
ec->gpe, ec->command_addr, ec->data_addr));
/* Boot EC is already working */
if (ec == boot_ec)
return 0;
return ec_install_handlers(ec);
}
static int acpi_ec_stop(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
acpi_status status;
struct acpi_ec *ec;
if (!device)
return -EINVAL;
ec = acpi_driver_data(device);
if (!ec)
return -EINVAL;
/* Don't touch boot EC */
if (ec == boot_ec)
return 0;
status = acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
......@@ -805,164 +772,67 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
return 0;
}
static acpi_status __init
acpi_fake_ecdt_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
static acpi_status
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
{
acpi_status status;
mutex_init(&ec_ecdt->lock);
atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
struct acpi_ec *ec = context;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec_ecdt);
ec_parse_io_ports, ec);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe);
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->global_lock = TRUE;
ec_ecdt->handle = handle;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
ec_ecdt->gpe, ec_ecdt->command_addr,
ec_ecdt->data_addr));
return AE_CTRL_TERMINATE;
}
/*
* Some BIOS (such as some from Gateway laptops) access EC region very early
* such as in BAT0._INI or EC._INI before an EC device is found and
* do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
* required, but if EC regison is accessed early, it is required.
* The routine tries to workaround the BIOS bug by pre-scan EC device
* It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
* op region (since _REG isn't invoked yet). The assumption is true for
* all systems found.
*/
static int __init acpi_ec_fake_ecdt(void)
{
acpi_status status;
int ret = 0;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT"));
ec->handle = handle;
ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec_ecdt) {
ret = -ENOMEM;
goto error;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
ec->gpe, ec->command_addr, ec->data_addr));
status = acpi_get_devices(ACPI_EC_HID,
acpi_fake_ecdt_callback, NULL, NULL);
if (ACPI_FAILURE(status)) {
kfree(ec_ecdt);
ec_ecdt = NULL;
ret = -ENODEV;
ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT"));
goto error;
}
return 0;
error:
return ret;
return AE_CTRL_TERMINATE;
}
static int __init acpi_ec_get_real_ecdt(void)
int __init acpi_ec_ecdt_probe(void)
{
int ret;
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_FAILURE(status))
return -ENODEV;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
boot_ec = make_acpi_ec();
if (!boot_ec)
return -ENOMEM;
/*
* Generate a temporary ec context to use until the namespace is scanned
* Generate a boot ec context
*/
ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec_ecdt)
return -ENOMEM;
mutex_init(&ec_ecdt->lock);
atomic_set(&ec_ecdt->event_count, 1);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
ec_ecdt->command_addr = ecdt_ptr->control.address;
ec_ecdt->data_addr = ecdt_ptr->data.address;
ec_ecdt->gpe = ecdt_ptr->gpe;
/* use the GL just to be safe */
ec_ecdt->global_lock = TRUE;
ec_ecdt->uid = ecdt_ptr->uid;
status = acpi_get_handle(NULL, ecdt_ptr->id, &ec_ecdt->handle);
if (ACPI_FAILURE(status)) {
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_FAILURE(status))
goto error;
}
return 0;
error:
ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
kfree(ec_ecdt);
ec_ecdt = NULL;
return -ENODEV;
}
static int __initdata acpi_fake_ecdt_enabled;
int __init acpi_ec_ecdt_probe(void)
{
acpi_status status;
int ret;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT"));
ret = acpi_ec_get_real_ecdt();
/* Try to make a fake ECDT */
if (ret && acpi_fake_ecdt_enabled) {
ret = acpi_ec_fake_ecdt();
}
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
if (ret)
ret = ec_install_handlers(boot_ec);
if (!ret) {
first_ec = boot_ec;
return 0;
/*
* Install GPE handler
*/
status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec_ecdt);
if (ACPI_FAILURE(status)) {
goto error;
}
acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
&acpi_ec_space_setup,
ec_ecdt);
if (ACPI_FAILURE(status)) {
acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
&acpi_ec_gpe_handler);
goto error;
}
return 0;
error:
ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
kfree(ec_ecdt);
ec_ecdt = NULL;
kfree(boot_ec);
boot_ec = NULL;
return -ENODEV;
}
......@@ -1003,13 +873,6 @@ static void __exit acpi_ec_exit(void)
}
#endif /* 0 */
static int __init acpi_fake_ecdt_setup(char *str)
{
acpi_fake_ecdt_enabled = 1;
return 1;
}
__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
static int __init acpi_ec_set_intr_mode(char *str)
{
int intr;
......@@ -1017,12 +880,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
if (!get_option(&str, &intr))
return 0;
if (intr) {
acpi_ec_mode = EC_INTR;
} else {
acpi_ec_mode = EC_POLL;
}
acpi_ec_driver.ops.add = acpi_ec_add;
acpi_ec_mode = (intr) ? EC_INTR : EC_POLL;
printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
return 1;
......
/*
* SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
*
* Copyright (c) 2002, 2005 Ducrot Bruno
* Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
*
* 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 version 2.
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include "i2c_ec.h"
#define xudelay(t) udelay(t)
#define xmsleep(t) msleep(t)
#define ACPI_EC_HC_COMPONENT 0x00080000
#define ACPI_EC_HC_CLASS "ec_hc_smbus"
#define ACPI_EC_HC_HID "ACPI0001"
#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
#define _COMPONENT ACPI_EC_HC_COMPONENT
ACPI_MODULE_NAME("i2c_ec");
static int acpi_ec_hc_add(struct acpi_device *device);
static int acpi_ec_hc_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_ec_hc_driver = {
.name = "i2c_ec",
.class = ACPI_EC_HC_CLASS,
.ids = ACPI_EC_HC_HID,
.ops = {
.add = acpi_ec_hc_add,
.remove = acpi_ec_hc_remove,
},
};
/* Various bit mask for EC_SC (R) */
#define OBF 0x01
#define IBF 0x02
#define CMD 0x08
#define BURST 0x10
#define SCI_EVT 0x20
#define SMI_EVT 0x40
/* Commands for EC_SC (W) */
#define RD_EC 0x80
#define WR_EC 0x81
#define BE_EC 0x82
#define BD_EC 0x83
#define QR_EC 0x84
/*
* ACPI 2.0 chapter 13 SMBus 2.0 EC register model
*/
#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
#define ACPI_EC_SMB_STS 0x01 /* status */
#define ACPI_EC_SMB_ADDR 0x02 /* address */
#define ACPI_EC_SMB_CMD 0x03 /* command */
#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
#define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */
#define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
#define ACPI_EC_SMB_STS_DONE 0x80
#define ACPI_EC_SMB_STS_ALRM 0x40
#define ACPI_EC_SMB_STS_RES 0x20
#define ACPI_EC_SMB_STS_STATUS 0x1f
#define ACPI_EC_SMB_STATUS_OK 0x00
#define ACPI_EC_SMB_STATUS_FAIL 0x07
#define ACPI_EC_SMB_STATUS_DNAK 0x10
#define ACPI_EC_SMB_STATUS_DERR 0x11
#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12
#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13
#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17
#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18
#define ACPI_EC_SMB_STATUS_NOTSUP 0x19
#define ACPI_EC_SMB_STATUS_BUSY 0x1A
#define ACPI_EC_SMB_STATUS_PEC 0x1F
#define ACPI_EC_SMB_PRTCL_WRITE 0x00
#define ACPI_EC_SMB_PRTCL_READ 0x01
#define ACPI_EC_SMB_PRTCL_QUICK 0x02
#define ACPI_EC_SMB_PRTCL_BYTE 0x04
#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06
#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c
#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define ACPI_EC_SMB_PRTCL_PEC 0x80
/* Length of pre/post transaction sleep (msec) */
#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
#define ACPI_EC_SMB_ACCESS_SLEEP1 1
#define ACPI_EC_SMB_ACCESS_SLEEP2 10
static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
{
u8 val;
int err;
err = ec_read(smbus->base + address, &val);
if (!err) {
*data = val;
}
xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
return (err);
}
static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
{
int err;
err = ec_write(smbus->base + address, data);
return (err);
}
static int
acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
char read_write, u8 command, int size,
union i2c_smbus_data *data)
{
struct acpi_ec_smbus *smbus = adap->algo_data;
unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
int i;
if (read_write == I2C_SMBUS_READ) {
protocol = ACPI_EC_SMB_PRTCL_READ;
} else {
protocol = ACPI_EC_SMB_PRTCL_WRITE;
}
pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
switch (size) {
case I2C_SMBUS_QUICK:
protocol |= ACPI_EC_SMB_PRTCL_QUICK;
read_write = I2C_SMBUS_WRITE;
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_WRITE) {
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
}
protocol |= ACPI_EC_SMB_PRTCL_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
if (read_write == I2C_SMBUS_WRITE) {
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
}
protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
if (read_write == I2C_SMBUS_WRITE) {
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
data->word >> 8);
}
protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
break;
case I2C_SMBUS_BLOCK_DATA:
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
if (read_write == I2C_SMBUS_WRITE) {
len = min_t(u8, data->block[0], 32);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
for (i = 0; i < len; i++)
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
data->block[i + 1]);
}
protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
len = min_t(u8, data->block[0], 32);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
if (read_write == I2C_SMBUS_WRITE) {
for (i = 0; i < len; i++) {
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
data->block[i + 1]);
}
}
protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
break;
case I2C_SMBUS_PROC_CALL:
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
read_write = I2C_SMBUS_READ;
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
protocol |= pec;
len = min_t(u8, data->block[0], 31);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
for (i = 0; i < len; i++)
acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
data->block[i + 1]);
protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
read_write = I2C_SMBUS_READ;
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: "
"Unsupported transaction %d\n", size));
return (-1);
}
acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
xudelay(500);
acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
}
if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
}
if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
|| (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
return (-1);
}
if (read_write == I2C_SMBUS_WRITE) {
return (0);
}
switch (size) {
case I2C_SMBUS_BYTE:
case I2C_SMBUS_BYTE_DATA:
acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
break;
case I2C_SMBUS_WORD_DATA:
case I2C_SMBUS_PROC_CALL:
acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
data->word = (temp[1] << 8) | temp[0];
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
len = 0;
acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
len = min_t(u8, len, 32);
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < len; i++)
acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
data->block + i + 1);
data->block[0] = len;
break;
}
return (0);
}
static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
{
return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA |
I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
}
static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
.smbus_xfer = acpi_ec_smb_access,
.functionality = acpi_ec_smb_func,
};
static int acpi_ec_hc_add(struct acpi_device *device)
{
int status;
unsigned long val;
struct acpi_ec_hc *ec_hc;
struct acpi_ec_smbus *smbus;
if (!device) {
return -EINVAL;
}
ec_hc = kzalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
if (!ec_hc) {
return -ENOMEM;
}
smbus = kzalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
if (!smbus) {
kfree(ec_hc);
return -ENOMEM;
}
ec_hc->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
acpi_driver_data(device) = ec_hc;
status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
kfree(ec_hc);
kfree(smbus);
return -EIO;
}
smbus->ec = acpi_driver_data(device->parent);
smbus->base = (val & 0xff00ull) >> 8;
smbus->alert = val & 0xffull;
smbus->adapter.owner = THIS_MODULE;
smbus->adapter.algo = &acpi_ec_smbus_algorithm;
smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &device->dev;
if (i2c_add_adapter(&smbus->adapter)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"EC SMBus adapter: Failed to register adapter\n"));
kfree(smbus);
kfree(ec_hc);
return -EIO;
}
ec_hc->smbus = smbus;
printk(KERN_INFO PREFIX "%s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
return AE_OK;
}
static int acpi_ec_hc_remove(struct acpi_device *device, int type)
{
struct acpi_ec_hc *ec_hc;
if (!device) {
return -EINVAL;
}
ec_hc = acpi_driver_data(device);
i2c_del_adapter(&ec_hc->smbus->adapter);
kfree(ec_hc->smbus);
kfree(ec_hc);
return AE_OK;
}
static int __init acpi_ec_hc_init(void)
{
int result;
result = acpi_bus_register_driver(&acpi_ec_hc_driver);
if (result < 0) {
return -ENODEV;
}
return 0;
}
static void __exit acpi_ec_hc_exit(void)
{
acpi_bus_unregister_driver(&acpi_ec_hc_driver);
}
struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
{
return acpi_driver_data(device->parent);
}
EXPORT_SYMBOL(acpi_get_ec_hc);
module_init(acpi_ec_hc_init);
module_exit(acpi_ec_hc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ducrot Bruno");
MODULE_DESCRIPTION("ACPI EC SMBus driver");
/*
* SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
*
* Copyright (c) 2002, 2005 Ducrot Bruno
*
* 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 version 2.
*/
struct acpi_ec_smbus {
struct i2c_adapter adapter;
union acpi_ec *ec;
int base;
int alert;
};
struct acpi_ec_hc {
acpi_handle handle;
struct acpi_ec_smbus *smbus;
};
struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
......@@ -70,8 +70,6 @@
#define ACPI_PROCESSOR_LIMIT_USER 0
#define ACPI_PROCESSOR_LIMIT_THERMAL 1
#define ACPI_STA_PRESENT 0x00000001
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_core");
......@@ -779,7 +777,7 @@ static int is_processor_present(acpi_handle handle)
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_PRESENT)) {
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) {
ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
return 0;
}
......
......@@ -51,14 +51,6 @@
#include <asm/apic.h>
#endif
/*
* Include the apic definitions for x86 to have the APIC timer related defines
* available also for UP (on SMP it gets magically included via linux/smp.h).
*/
#ifdef CONFIG_X86
#include <asm/apic.h>
#endif
#include <asm/io.h>
#include <asm/uaccess.h>
......
此差异已折叠。
......@@ -1068,7 +1068,9 @@ acpi_add_single_object(struct acpi_device **child,
}
break;
default:
STRUCT_TO_INT(device->status) = 0x0F;
STRUCT_TO_INT(device->status) =
ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
break;
}
......
......@@ -350,21 +350,31 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
{
struct list_head *node, *next;
seq_printf(seq, "Device Sleep state Status\n");
seq_printf(seq, "Device\tS-state\t Status Sysfs node\n");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
struct device *ldev;
if (!dev->wakeup.flags.valid)
continue;
spin_unlock(&acpi_device_lock);
seq_printf(seq, "%4s %4d %s%8s\n",
ldev = acpi_get_physical_device(dev->handle);
seq_printf(seq, "%s\t S%d\t%c%-8s ",
dev->pnp.bus_id,
(u32) dev->wakeup.sleep_state,
dev->wakeup.flags.run_wake ? "*" : "",
dev->wakeup.flags.run_wake ? '*' : ' ',
dev->wakeup.state.enabled ? "enabled" : "disabled");
if (ldev)
seq_printf(seq, "%s:%s",
ldev->bus ? ldev->bus->name : "no-bus",
ldev->bus_id);
seq_printf(seq, "\n");
put_device(ldev);
spin_lock(&acpi_device_lock);
}
spin_unlock(&acpi_device_lock);
......
......@@ -347,6 +347,18 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
}
/*
* For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero)
* are indeed zero. This will workaround BIOSs that inadvertently placed
* values in these fields.
*/
if (acpi_gbl_FADT.header.revision < 3) {
acpi_gbl_FADT.preferred_profile = 0;
acpi_gbl_FADT.pstate_control = 0;
acpi_gbl_FADT.cst_control = 0;
acpi_gbl_FADT.boot_flags = 0;
}
}
/******************************************************************************
......
/*
* Sony Programmable I/O Control Device driver for VAIO
*
* Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
*
* Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
*
* Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
......@@ -95,6 +97,11 @@ module_param(useinput, int, 0444);
MODULE_PARM_DESC(useinput,
"set this if you would like sonypi to feed events to the input subsystem");
static int check_ioport = 1;
module_param(check_ioport, int, 0444);
MODULE_PARM_DESC(check_ioport,
"set this to 0 if you think the automatic ioport check for sony-laptop is wrong");
#define SONYPI_DEVICE_MODEL_TYPE1 1
#define SONYPI_DEVICE_MODEL_TYPE2 2
#define SONYPI_DEVICE_MODEL_TYPE3 3
......@@ -477,7 +484,7 @@ static struct sonypi_device {
u16 evtype_offset;
int camera_power;
int bluetooth_power;
struct semaphore lock;
struct mutex lock;
struct kfifo *fifo;
spinlock_t fifo_lock;
wait_queue_head_t fifo_proc_list;
......@@ -884,7 +891,7 @@ int sonypi_camera_command(int command, u8 value)
if (!camera)
return -EIO;
down(&sonypi_device.lock);
mutex_lock(&sonypi_device.lock);
switch (command) {
case SONYPI_COMMAND_SETCAMERA:
......@@ -919,7 +926,7 @@ int sonypi_camera_command(int command, u8 value)
command);
break;
}
up(&sonypi_device.lock);
mutex_unlock(&sonypi_device.lock);
return 0;
}
......@@ -938,20 +945,20 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on)
static int sonypi_misc_release(struct inode *inode, struct file *file)
{
sonypi_misc_fasync(-1, file, 0);
down(&sonypi_device.lock);
mutex_lock(&sonypi_device.lock);
sonypi_device.open_count--;
up(&sonypi_device.lock);
mutex_unlock(&sonypi_device.lock);
return 0;
}
static int sonypi_misc_open(struct inode *inode, struct file *file)
{
down(&sonypi_device.lock);
mutex_lock(&sonypi_device.lock);
/* Flush input queue on first open */
if (!sonypi_device.open_count)
kfifo_reset(sonypi_device.fifo);
sonypi_device.open_count++;
up(&sonypi_device.lock);
mutex_unlock(&sonypi_device.lock);
return 0;
}
......@@ -1001,7 +1008,7 @@ static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
u8 val8;
u16 val16;
down(&sonypi_device.lock);
mutex_lock(&sonypi_device.lock);
switch (cmd) {
case SONYPI_IOCGBRT:
if (sonypi_ec_read(SONYPI_LCD_LIGHT, &val8)) {
......@@ -1101,7 +1108,7 @@ static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
default:
ret = -EINVAL;
}
up(&sonypi_device.lock);
mutex_unlock(&sonypi_device.lock);
return ret;
}
......@@ -1260,6 +1267,28 @@ static int __devinit sonypi_create_input_devices(void)
static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
const struct sonypi_ioport_list *ioport_list)
{
/* try to detect if sony-laptop is being used and thus
* has already requested one of the known ioports.
* As in the deprecated check_region this is racy has we have
* multiple ioports available and one of them can be requested
* between this check and the subsequent request. Anyway, as an
* attempt to be some more user-friendly as we currently are,
* this is enough.
*/
const struct sonypi_ioport_list *check = ioport_list;
while (check_ioport && check->port1) {
if (!request_region(check->port1,
sonypi_device.region_size,
"Sony Programable I/O Device Check")) {
printk(KERN_ERR "sonypi: ioport 0x%.4x busy, using sony-laptop? "
"if not use check_ioport=0\n",
check->port1);
return -EBUSY;
}
release_region(check->port1, sonypi_device.region_size);
check++;
}
while (ioport_list->port1) {
if (request_region(ioport_list->port1,
......@@ -1321,6 +1350,10 @@ static int __devinit sonypi_probe(struct platform_device *dev)
struct pci_dev *pcidev;
int error;
printk(KERN_WARNING "sonypi: please try the sony-laptop module instead "
"and report failures, see also "
"http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n");
spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock);
......@@ -1330,7 +1363,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
}
init_waitqueue_head(&sonypi_device.fifo_proc_list);
init_MUTEX(&sonypi_device.lock);
mutex_init(&sonypi_device.lock);
sonypi_device.bluetooth_power = -1;
if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
......
......@@ -26,7 +26,7 @@
/*
* The I/O port the PMTMR resides at.
* The location is detected during setup_arch(),
* in arch/i386/acpi/boot.c
* in arch/i386/kernel/acpi/boot.c
*/
u32 pmtmr_ioport __read_mostly;
......
......@@ -577,14 +577,14 @@ config VIDEO_ZORAN_AVS6EYES
config VIDEO_MEYE
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
depends on PCI && SONYPI && VIDEO_V4L1
depends on PCI && SONY_LAPTOP && VIDEO_V4L1
---help---
This is the video4linux driver for the Motion Eye camera found
in the Vaio Picturebook laptops. Please read the material in
<file:Documentation/video4linux/meye.txt> for more information.
If you say Y or M here, you need to say Y or M to "Sony Programmable
I/O Control Device" in the character device section.
If you say Y or M here, you need to say Y or M to "Sony Laptop
Extras" in the misc device section.
To compile this driver as a module, choose M here: the
module will be called meye.
......
......@@ -925,13 +925,13 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
return -EINVAL;
mutex_lock(&meye.lock);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
p->brightness >> 10);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
p->hue >> 10);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
p->colour >> 10);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
p->contrast >> 10);
meye.picture = *p;
mutex_unlock(&meye.lock);
......@@ -1043,11 +1043,11 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
meye.params.quality != jp->quality)
mchip_hic_stop(); /* need restart */
meye.params = *jp;
sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
meye.params.sharpness);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
meye.params.agc);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE,
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
meye.params.picture);
mutex_unlock(&meye.lock);
break;
......@@ -1287,38 +1287,38 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&meye.lock);
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERABRIGHTNESS, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
meye.picture.brightness = c->value << 10;
break;
case V4L2_CID_HUE:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERAHUE, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
meye.picture.hue = c->value << 10;
break;
case V4L2_CID_CONTRAST:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERACONTRAST, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
meye.picture.contrast = c->value << 10;
break;
case V4L2_CID_SATURATION:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERACOLOR, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
meye.picture.colour = c->value << 10;
break;
case V4L2_CID_AGC:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERAAGC, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
meye.params.agc = c->value;
break;
case V4L2_CID_SHARPNESS:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERASHARPNESS, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
meye.params.sharpness = c->value;
break;
case V4L2_CID_PICTURE:
sonypi_camera_command(
SONYPI_COMMAND_SETCAMERAPICTURE, c->value);
sony_pic_camera_command(
SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
meye.params.picture = c->value;
break;
case V4L2_CID_JPEGQUAL:
......@@ -1848,7 +1848,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
meye.video_dev->dev = &meye.mchip_dev->dev;
if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) {
if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
printk(KERN_ERR "meye: unable to power on the camera\n");
printk(KERN_ERR "meye: did you enable the camera in "
"sonypi using the module options ?\n");
......@@ -1928,13 +1928,13 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
meye.params.picture = 0;
meye.params.framerate = 0;
sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 32);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 32);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 32);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 32);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, 32);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 0);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
MEYE_DRIVER_VERSION);
......@@ -1953,7 +1953,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
outregions:
pci_disable_device(meye.mchip_dev);
outenabledev:
sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
outsonypienable:
kfifo_free(meye.doneq);
outkfifoalloc2:
......@@ -1986,7 +1986,7 @@ static void __devexit meye_remove(struct pci_dev *pcidev)
pci_disable_device(meye.mchip_dev);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);
sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
kfifo_free(meye.doneq);
kfifo_free(meye.grabq);
......
......@@ -255,7 +255,7 @@
/****************************************************************************/
/* Sony Programmable I/O Controller for accessing the camera commands */
#include <linux/sonypi.h>
#include <linux/sony-laptop.h>
/* private API definitions */
#include <linux/meye.h>
......
......@@ -112,14 +112,70 @@ config SONY_LAPTOP
depends on X86 && ACPI
select BACKLIGHT_CLASS_DEVICE
---help---
This mini-driver drives the SNC device present in the ACPI BIOS of
the Sony Vaio laptops.
This mini-driver drives the SNC and SPIC devices present in the ACPI
BIOS of the Sony Vaio laptops.
It gives access to some extra laptop functionalities. In its current
form, this driver let the user set or query the screen brightness
through the backlight subsystem and remove/apply power to some
It gives access to some extra laptop functionalities like Bluetooth,
screen brightness control, Fn keys and allows powering on/off some
devices.
Read <file:Documentation/sony-laptop.txt> for more information.
config SONY_LAPTOP_OLD
bool "Sonypi compatibility"
depends on SONY_LAPTOP
---help---
Build the sonypi driver compatibility code into the sony-laptop driver.
config THINKPAD_ACPI
tristate "ThinkPad ACPI Laptop Extras"
depends on X86 && ACPI
select BACKLIGHT_CLASS_DEVICE
select HWMON
---help---
This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
output switching, ThinkLight control, UltraBay eject and more.
For more information about this driver see
<file:Documentation/thinkpad-acpi.txt> and <http://ibm-acpi.sf.net/> .
This driver was formely known as ibm-acpi.
If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
config THINKPAD_ACPI_DEBUG
bool "Verbose debug mode"
depends on THINKPAD_ACPI
default n
---help---
Enables extra debugging information, at the expense of a slightly
increase in driver size.
If you are not sure, say N here.
config THINKPAD_ACPI_DOCK
bool "Legacy Docking Station Support"
depends on THINKPAD_ACPI
depends on ACPI_DOCK=n
default n
---help---
Allows the thinkpad_acpi driver to handle docking station events.
This support was made obsolete by the generic ACPI docking station
support (CONFIG_ACPI_DOCK). It will allow locking and removing the
laptop from the docking station, but will not properly connect PCI
devices.
If you are not sure, say N here.
config THINKPAD_ACPI_BAY
bool "Legacy Removable Bay Support"
depends on THINKPAD_ACPI
default y
---help---
Allows the thinkpad_acpi driver to handle removable bays. It will
eletrically disable the device in the bay, and also generate
notifications when the bay lever is ejected or inserted.
If you are not sure, say Y here.
endmenu
......@@ -12,3 +12,4 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -317,6 +317,10 @@ static int __init acpi_pci_init(void)
{
int ret;
if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) {
printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
pci_no_msi();
}
ret = register_acpi_bus_type(&acpi_pci_bus);
if (ret)
return 0;
......
......@@ -276,6 +276,7 @@ enum acpi_prefered_pm_profiles {
#define BAF_LEGACY_DEVICES 0x0001
#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
#define BAF_MSI_NOT_SUPPORTED 0x0008
#define FADT2_REVISION_ID 3
#define FADT2_MINUS_REVISION_ID 2
......
#ifndef _SONYLAPTOP_H_
#define _SONYLAPTOP_H_
#include <linux/types.h>
#ifdef __KERNEL__
/* used only for communication between v4l and sony-laptop */
#define SONY_PIC_COMMAND_GETCAMERA 1 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERA 2
#define SONY_PIC_COMMAND_GETCAMERABRIGHTNESS 3 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERABRIGHTNESS 4
#define SONY_PIC_COMMAND_GETCAMERACONTRAST 5 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACONTRAST 6
#define SONY_PIC_COMMAND_GETCAMERAHUE 7 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAHUE 8
#define SONY_PIC_COMMAND_GETCAMERACOLOR 9 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACOLOR 10
#define SONY_PIC_COMMAND_GETCAMERASHARPNESS 11 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERASHARPNESS 12
#define SONY_PIC_COMMAND_GETCAMERAPICTURE 13 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAPICTURE 14
#define SONY_PIC_COMMAND_GETCAMERAAGC 15 /* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAAGC 16
#define SONY_PIC_COMMAND_GETCAMERADIRECTION 17 /* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAROMVERSION 18 /* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAREVISION 19 /* obsolete */
int sony_pic_camera_command(int command, u8 value);
#endif /* __KERNEL__ */
#endif /* _SONYLAPTOP_H_ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册