diff options
| author | Yin Kangkai <kangkai.yin@linux.intel.com> | 2011-04-06 10:05:24 -0400 |
|---|---|---|
| committer | Matthew Garrett <mjg@redhat.com> | 2011-05-27 12:36:43 -0400 |
| commit | bb3ce2020451bdebe5ceac770504f427724008a9 (patch) | |
| tree | 1f2e3fa0a8b6f8262f2cc33164efc934cb45008a /drivers/platform | |
| parent | 0978e012cfbaca8bd312933e98cdea2d11778e11 (diff) | |
platform/oaktrail: ACPI EC Extra driver for Oaktrail
This driver implements an Extra ACPI EC driver for products based on Intel
Oaktrail platform.
This driver does below things:
1. registers itself in the Linux backlight control in
/sys/class/backlight/intel_oaktrail/
2. registers in the rfkill subsystem here: /sys/class/rfkill/rfkillX/
for these components: wifi, bluetooth, wwan (3g), gps
Signed-off-by: Yin Kangkai <kangkai.yin@linux.intel.com>
[Extracted from a bigger patch by Yin Kangkai, this version leaves out some
sysfs bits that probably want to be driver managed, and ACPI i2c enumeration]
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
| -rw-r--r-- | drivers/platform/x86/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/Makefile | 1 | ||||
| -rw-r--r-- | drivers/platform/x86/intel_oaktrail.c | 396 |
3 files changed, 406 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 5cb999b50f95..83c2411acb5b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -760,4 +760,13 @@ config MXM_WMI | |||
| 760 | MXM is a standard for laptop graphics cards, the WMI interface | 760 | MXM is a standard for laptop graphics cards, the WMI interface |
| 761 | is required for switchable nvidia graphics machines | 761 | is required for switchable nvidia graphics machines |
| 762 | 762 | ||
| 763 | config INTEL_OAKTRAIL | ||
| 764 | tristate "Intel Oaktrail Platform Extras" | ||
| 765 | depends on ACPI | ||
| 766 | depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI | ||
| 767 | ---help--- | ||
| 768 | Intel Oaktrail platform need this driver to provide interfaces to | ||
| 769 | enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y | ||
| 770 | here; it will only load on supported platforms. | ||
| 771 | |||
| 763 | endif # X86_PLATFORM_DEVICES | 772 | endif # X86_PLATFORM_DEVICES |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index a7ab3bc7b3a1..af683fb5a807 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -43,3 +43,4 @@ obj-$(CONFIG_IBM_RTL) += ibm_rtl.o | |||
| 43 | obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o | 43 | obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o |
| 44 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o | 44 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o |
| 45 | obj-$(CONFIG_MXM_WMI) += mxm-wmi.o | 45 | obj-$(CONFIG_MXM_WMI) += mxm-wmi.o |
| 46 | obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o | ||
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c new file mode 100644 index 000000000000..e936364a609d --- /dev/null +++ b/drivers/platform/x86/intel_oaktrail.c | |||
| @@ -0,0 +1,396 @@ | |||
| 1 | /* | ||
| 2 | * intel_oaktrail.c - Intel OakTrail Platform support. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010-2011 Intel Corporation | ||
| 5 | * Author: Yin Kangkai (kangkai.yin@intel.com) | ||
| 6 | * | ||
| 7 | * based on Compal driver, Copyright (C) 2008 Cezary Jackiewicz | ||
| 8 | * <cezary.jackiewicz (at) gmail.com>, based on MSI driver | ||
| 9 | * Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, but | ||
| 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | * General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 24 | * 02110-1301, USA. | ||
| 25 | * | ||
| 26 | * This driver does below things: | ||
| 27 | * 1. registers itself in the Linux backlight control in | ||
| 28 | * /sys/class/backlight/intel_oaktrail/ | ||
| 29 | * | ||
| 30 | * 2. registers in the rfkill subsystem here: /sys/class/rfkill/rfkillX/ | ||
| 31 | * for these components: wifi, bluetooth, wwan (3g), gps | ||
| 32 | * | ||
| 33 | * This driver might work on other products based on Oaktrail. If you | ||
| 34 | * want to try it you can pass force=1 as argument to the module which | ||
| 35 | * will force it to load even when the DMI data doesn't identify the | ||
| 36 | * product as compatible. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 40 | |||
| 41 | #include <linux/module.h> | ||
| 42 | #include <linux/kernel.h> | ||
| 43 | #include <linux/init.h> | ||
| 44 | #include <linux/acpi.h> | ||
| 45 | #include <linux/fb.h> | ||
| 46 | #include <linux/mutex.h> | ||
| 47 | #include <linux/err.h> | ||
| 48 | #include <linux/i2c.h> | ||
| 49 | #include <linux/backlight.h> | ||
| 50 | #include <linux/platform_device.h> | ||
| 51 | #include <linux/dmi.h> | ||
| 52 | #include <linux/rfkill.h> | ||
| 53 | #include <acpi/acpi_bus.h> | ||
| 54 | #include <acpi/acpi_drivers.h> | ||
| 55 | |||
| 56 | |||
| 57 | #define DRIVER_NAME "intel_oaktrail" | ||
| 58 | #define DRIVER_VERSION "0.4ac1" | ||
| 59 | |||
| 60 | /* | ||
| 61 | * This is the devices status address in EC space, and the control bits | ||
| 62 | * definition: | ||
| 63 | * | ||
| 64 | * (1 << 0): Camera enable/disable, RW. | ||
| 65 | * (1 << 1): Bluetooth enable/disable, RW. | ||
| 66 | * (1 << 2): GPS enable/disable, RW. | ||
| 67 | * (1 << 3): WiFi enable/disable, RW. | ||
| 68 | * (1 << 4): WWAN (3G) enable/disalbe, RW. | ||
| 69 | * (1 << 5): Touchscreen enable/disable, Read Only. | ||
| 70 | */ | ||
| 71 | #define OT_EC_DEVICE_STATE_ADDRESS 0xD6 | ||
| 72 | |||
| 73 | #define OT_EC_CAMERA_MASK (1 << 0) | ||
| 74 | #define OT_EC_BT_MASK (1 << 1) | ||
| 75 | #define OT_EC_GPS_MASK (1 << 2) | ||
| 76 | #define OT_EC_WIFI_MASK (1 << 3) | ||
| 77 | #define OT_EC_WWAN_MASK (1 << 4) | ||
| 78 | #define OT_EC_TS_MASK (1 << 5) | ||
| 79 | |||
| 80 | /* | ||
| 81 | * This is the address in EC space and commands used to control LCD backlight: | ||
| 82 | * | ||
| 83 | * Two steps needed to change the LCD backlight: | ||
| 84 | * 1. write the backlight percentage into OT_EC_BL_BRIGHTNESS_ADDRESS; | ||
| 85 | * 2. write OT_EC_BL_CONTROL_ON_DATA into OT_EC_BL_CONTROL_ADDRESS. | ||
| 86 | * | ||
| 87 | * To read the LCD back light, just read out the value from | ||
| 88 | * OT_EC_BL_BRIGHTNESS_ADDRESS. | ||
| 89 | * | ||
| 90 | * LCD backlight brightness range: 0 - 100 (OT_EC_BL_BRIGHTNESS_MAX) | ||
| 91 | */ | ||
| 92 | #define OT_EC_BL_BRIGHTNESS_ADDRESS 0x44 | ||
| 93 | #define OT_EC_BL_BRIGHTNESS_MAX 100 | ||
| 94 | #define OT_EC_BL_CONTROL_ADDRESS 0x3A | ||
| 95 | #define OT_EC_BL_CONTROL_ON_DATA 0x1A | ||
| 96 | |||
| 97 | |||
| 98 | static int force; | ||
| 99 | module_param(force, bool, 0); | ||
| 100 | MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); | ||
| 101 | |||
| 102 | static struct platform_device *oaktrail_device; | ||
| 103 | static struct backlight_device *oaktrail_bl_device; | ||
| 104 | static struct rfkill *bt_rfkill; | ||
| 105 | static struct rfkill *gps_rfkill; | ||
| 106 | static struct rfkill *wifi_rfkill; | ||
| 107 | static struct rfkill *wwan_rfkill; | ||
| 108 | |||
| 109 | |||
| 110 | /* rfkill */ | ||
| 111 | static int oaktrail_rfkill_set(void *data, bool blocked) | ||
| 112 | { | ||
| 113 | u8 value; | ||
| 114 | u8 result; | ||
| 115 | unsigned long radio = (unsigned long) data; | ||
| 116 | |||
| 117 | ec_read(OT_EC_DEVICE_STATE_ADDRESS, &result); | ||
| 118 | |||
| 119 | if (!blocked) | ||
| 120 | value = (u8) (result | radio); | ||
| 121 | else | ||
| 122 | value = (u8) (result & ~radio); | ||
| 123 | |||
| 124 | ec_write(OT_EC_DEVICE_STATE_ADDRESS, value); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static const struct rfkill_ops oaktrail_rfkill_ops = { | ||
| 130 | .set_block = oaktrail_rfkill_set, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static struct rfkill *oaktrail_rfkill_new(char *name, enum rfkill_type type, | ||
| 134 | unsigned long mask) | ||
| 135 | { | ||
| 136 | struct rfkill *rfkill_dev; | ||
| 137 | u8 value; | ||
| 138 | int err; | ||
| 139 | |||
| 140 | rfkill_dev = rfkill_alloc(name, &oaktrail_device->dev, type, | ||
| 141 | &oaktrail_rfkill_ops, (void *)mask); | ||
| 142 | if (!rfkill_dev) | ||
| 143 | return ERR_PTR(-ENOMEM); | ||
| 144 | |||
| 145 | ec_read(OT_EC_DEVICE_STATE_ADDRESS, &value); | ||
| 146 | rfkill_init_sw_state(rfkill_dev, (value & mask) != 1); | ||
| 147 | |||
| 148 | err = rfkill_register(rfkill_dev); | ||
| 149 | if (err) { | ||
| 150 | rfkill_destroy(rfkill_dev); | ||
| 151 | return ERR_PTR(err); | ||
| 152 | } | ||
| 153 | |||
| 154 | return rfkill_dev; | ||
| 155 | } | ||
| 156 | |||
| 157 | static inline void __oaktrail_rfkill_cleanup(struct rfkill *rf) | ||
