Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 - big update to Wacom driver by Benjamin Tissoires, converting it to
   HID infrastructure and unifying USB and Bluetooth models
 - large update to ALPS driver by Hans de Goede, which adds support for
   newer touchpad models as well as cleans up and restructures the code
 - more changes to Atmel MXT driver, including device tree support
 - new driver for iPaq x3xxx touchscreen
 - driver for serial Wacom tablets
 - driver for Microchip's CAP1106
 - assorted cleanups and improvements to existing drover and input core

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (93 commits)
  Input: wacom - update the ABI doc according to latest changes
  Input: wacom - only register once the MODULE_* macros
  Input: HID - remove hid-wacom Bluetooth driver
  Input: wacom - add copyright note and bump version to 2.0
  Input: wacom - remove passing id for wacom_set_report
  Input: wacom - check for bluetooth protocol while setting OLEDs
  Input: wacom - handle Intuos 4 BT in wacom.ko
  Input: wacom - handle Graphire BT tablets in wacom.ko
  Input: wacom - prepare the driver to include BT devices
  Input: hyperv-keyboard - register as a wakeup source
  Input: imx_keypad - remove ifdef round PM methods
  Input: jornada720_ts - get rid of space indentation and use tab
  Input: jornada720_ts - switch to using managed resources
  Input: alps - Rushmore and v7 resolution support
  Input: mcs5000_ts - remove ifdef around power management methods
  Input: mcs5000_ts - protect PM functions with CONFIG_PM_SLEEP
  Input: ads7846 - release resources on failure for clean exit
  Input: wacom - add support for 0x12C ISDv4 sensor
  Input: atmel_mxt_ts - use deep sleep mode when stopped
  ARM: dts: am437x-gp-evm: Update binding for touchscreen size
  ...
This commit is contained in:
Linus Torvalds
2014-08-08 17:39:48 -07:00
48 changed files with 4541 additions and 2911 deletions
+27 -43
View File
@@ -1,48 +1,27 @@
WWhat: /sys/class/hidraw/hidraw*/device/oled*_img
Date: June 2012
Contact: linux-bluetooth@vger.kernel.org
Description:
The /sys/class/hidraw/hidraw*/device/oled*_img files control
OLED mocro displays on Intuos4 Wireless tablet. Accepted image
has to contain 256 bytes (64x32 px 1 bit colour). The format
is the same as PBM image 62x32px without header (64 bits per
horizontal line, 32 lines). An example of setting OLED No. 0:
dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img
The attribute is read only and no local copy of the image is
stored.
What: /sys/class/hidraw/hidraw*/device/speed
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed
Date: April 2010
Kernel Version: 2.6.35
Contact: linux-bluetooth@vger.kernel.org
Description:
The /sys/class/hidraw/hidraw*/device/speed file controls
reporting speed of Wacom bluetooth tablet. Reading from
this file returns 1 if tablet reports in high speed mode
The /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed file
controls reporting speed of Wacom bluetooth tablet. Reading
from this file returns 1 if tablet reports in high speed mode
or 0 otherwise. Writing to this file one of these values
switches reporting speed.
What: /sys/class/leds/0005\:056A\:00BD.0001\:selector\:*/
Date: May 2012
Kernel Version: 3.5
Contact: linux-bluetooth@vger.kernel.org
Description:
LED selector for Intuos4 WL. There are 4 leds, but only one LED
can be lit at a time. Max brightness is 127.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/led
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Attribute group for control of the status LEDs and the OLEDs.
This attribute group is only available for Intuos 4 M, L,
and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq
21UX2 and Cintiq 24HD (LEDs only). Therefore its presence
implicitly signifies the presence of said LEDs and OLEDs on the
tablet device.
and XL (with LEDs and OLEDs), Intuos 4 WL, Intuos 5 (LEDs only),
Intuos Pro (LEDs only) and Cintiq 21UX2 and Cintiq 24HD
(LEDs only). Therefore its presence implicitly signifies the
presence of said LEDs and OLEDs on the tablet device.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status0_luminance
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the status LED luminance (1..127)
@@ -50,16 +29,16 @@ Description:
button is pressed on the stylus. This luminance level is
normally lower than the level when a button is pressed.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status1_luminance
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the status LED luminance (1..127)
when the stylus touches the tablet surface, or any button is
pressed on the stylus.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led0_select
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets which one of the four (for Intuos 4
@@ -67,23 +46,23 @@ Description:
24HD) status LEDs is active (0..3). The other three LEDs on the
same side are always inactive.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
Date: September 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led1_select
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets which one of the left four (for Cintiq 21UX2
and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on
the left are always inactive.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/buttons_luminance
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the overall luminance level (0..15)
of all eight button OLED displays.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
Date: August 2011
What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/button<n>_rawimg
Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
When writing a 1024 byte raw image in Wacom Intuos 4
@@ -93,3 +72,8 @@ Description:
byte chunk encodes the image data for two consecutive lines on
the display. The low nibble of each byte contains the first
line, and the high nibble contains the second line.
When the Wacom Intuos 4 is connected over Bluetooth, the
image has to contain 256 bytes (64x32 px 1 bit colour).
The format is also scrambled, like in the USB mode, and it can
be summarized by converting 76543210 into GECA6420.
HGFEDCBA HFDB7531
@@ -0,0 +1,25 @@
Atmel maXTouch touchscreen/touchpad
Required properties:
- compatible:
atmel,maxtouch
- reg: The I2C address of the device
- interrupts: The sink for the touchpad's IRQ output
See ../interrupt-controller/interrupts.txt
Optional properties for main touchpad device:
- linux,gpio-keymap: An array of up to 4 entries indicating the Linux
keycode generated by each GPIO. Linux keycodes are defined in
<dt-bindings/input/input.h>.
Example:
touch@4b {
compatible = "atmel,maxtouch";
reg = <0x4b>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_LOW>;
};
@@ -0,0 +1,53 @@
Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
The node for this driver must be a child of a I2C controller node, as the
device communication via I2C only.
Required properties:
compatible: Must be "microchip,cap1106"
reg: The I2C slave address of the device.
Only 0x28 is valid.
interrupts: Property describing the interrupt line the
device's ALERT#/CM_IRQ# pin is connected to.
The device only has one interrupt source.
Optional properties:
autorepeat: Enables the Linux input system's autorepeat
feature on the input device.
microchip,sensor-gain: Defines the gain of the sensor circuitry. This
effectively controls the sensitivity, as a
smaller delta capacitance is required to
generate the same delta count values.
Valid values are 1, 2, 4, and 8.
By default, a gain of 1 is set.
linux,keycodes: Specifies an array of numeric keycode values to
be used for the channels. If this property is
omitted, KEY_A, KEY_B, etc are used as
defaults. The array must have exactly six
entries.
Example:
i2c_controller {
cap1106@28 {
compatible = "microchip,cap1106";
interrupt-parent = <&gpio1>;
interrupts = <0 0>;
reg = <0x28>;
autorepeat;
microchip,sensor-gain = <2>;
linux,keycodes = <103 /* KEY_UP */
106 /* KEY_RIGHT */
108 /* KEY_DOWN */
105 /* KEY_LEFT */
109 /* KEY_PAGEDOWN */
104>; /* KEY_PAGEUP */
};
}
@@ -0,0 +1,26 @@
* Pixcir I2C touchscreen controllers
Required properties:
- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
- reg: I2C address of the chip
- interrupts: interrupt to which the chip is connected
- attb-gpio: GPIO connected to the ATTB line of the chip
- touchscreen-size-x: horizontal resolution of touchscreen (in pixels)
- touchscreen-size-y: vertical resolution of touchscreen (in pixels)
Example:
i2c@00000000 {
/* ... */
pixcir_ts@5c {
compatible = "pixcir,pixcir_ts";
reg = <0x5c>;
interrupts = <2 0>;
attb-gpio = <&gpf 2 0 2>;
touchscreen-size-x = <800>;
touchscreen-size-y = <600>;
};
/* ... */
};
@@ -9,6 +9,9 @@ Required properties:
- x-size: horizontal resolution of touchscreen
- y-size: vertical resolution of touchscreen
Optional properties:
- vdd-supply: Regulator controlling the controller supply
Example:
i2c@00000000 {
@@ -18,6 +21,7 @@ Example:
compatible = "neonode,zforce";
reg = <0x50>;
interrupts = <2 0>;
vdd-supply = <&reg_zforce_vdd>;
gpios = <&gpio5 6 0>, /* INT */
<&gpio5 9 0>; /* RST */
@@ -103,6 +103,7 @@ panasonic Panasonic Corporation
phytec PHYTEC Messtechnik GmbH
picochip Picochip Ltd
plathome Plat'Home Co., Ltd.
pixcir PIXCIR MICROELECTRONICS Co., Ltd
powervr PowerVR (deprecated, use img)
qca Qualcomm Atheros, Inc.
qcom Qualcomm Technologies, Inc
+7
View File
@@ -9877,6 +9877,13 @@ M: Pierre Ossman <pierre@ossman.eu>
S: Maintained
F: drivers/mmc/host/wbsd.*
WACOM PROTOCOL 4 SERIAL TABLETS
M: Julian Squires <julian@cipht.net>
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/tablet/wacom_serial4.c
WATCHDOG DEVICE DRIVERS
M: Wim Van Sebroeck <wim@iguana.be>
L: linux-watchdog@vger.kernel.org
+2 -2
View File
@@ -334,8 +334,8 @@
attb-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
x-size = <1024>;
y-size = <600>;
touchscreen-size-x = <1024>;
touchscreen-size-y = <600>;
};
};
+2 -2
View File
@@ -403,8 +403,8 @@
attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
x-size = <1024>;
y-size = <600>;
touchscreen-size-x = <1024>;
touchscreen-size-y = <600>;
};
};
+9 -4
View File
@@ -764,12 +764,17 @@ config THRUSTMASTER_FF
Rumble Force or Force Feedback Wheel.
config HID_WACOM
tristate "Wacom Bluetooth devices support"
tristate "Wacom Intuos/Graphire tablet support (USB)"
depends on HID
depends on LEDS_CLASS
select POWER_SUPPLY
---help---
Support for Wacom Graphire Bluetooth and Intuos4 WL tablets.
select NEW_LEDS
select LEDS_CLASS
help
Say Y here if you want to use the USB or BT version of the Wacom Intuos
or Graphire tablet.
To compile this driver as a module, choose M here: the
module will be called wacom.
config HID_WIIMOTE
tristate "Nintendo Wii / Wii U peripherals"
+3 -1
View File
@@ -116,7 +116,9 @@ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
obj-$(CONFIG_HID_WACOM) += hid-wacom.o
wacom-objs := wacom_wac.o wacom_sys.o
obj-$(CONFIG_HID_WACOM) += wacom.o
obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
+9 -3
View File
@@ -789,6 +789,15 @@ static int hid_scan_report(struct hid_device *hid)
/* hid-rmi should take care of them, not hid-generic */
hid->group = HID_GROUP_RMI;
/*
* Vendor specific handlings
*/
switch (hid->vendor) {
case USB_VENDOR_ID_WACOM:
hid->group = HID_GROUP_WACOM;
break;
}
vfree(parser);
return 0;
}
@@ -1938,8 +1947,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
@@ -2345,7 +2352,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
File diff suppressed because it is too large Load Diff
@@ -12,6 +12,7 @@
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
* Copyright (c) 2002-2011 Ping Cheng <pingc@wacom.com>
* Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@redhat.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -72,6 +73,8 @@
* v1.52 (pc) - Query Wacom data upon system resume
* - add defines for features->type
* - add new devices (0x9F, 0xE2, and 0XE3)
* v2.00 (bt) - conversion to a HID driver
* - integration of the Bluetooth devices
*/
/*
@@ -93,35 +96,30 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.53"
#define DRIVER_VERSION "v2.00"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom tablet driver"
#define DRIVER_LICENSE "GPL"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_WACOM 0x056a
#define USB_VENDOR_ID_LENOVO 0x17ef
struct wacom {
dma_addr_t data_dma;
struct usb_device *usbdev;
struct usb_interface *intf;
struct urb *irq;
struct wacom_wac wacom_wac;
struct hid_device *hdev;
struct mutex lock;
struct work_struct work;
bool open;
char phys[32];
struct wacom_led {
u8 select[2]; /* status led selector (0..3) */
u8 llv; /* status led brightness no button (1..127) */
u8 hlv; /* status led brightness button pressed (1..127) */
u8 img_lum; /* OLED matrix display brightness */
} led;
bool led_initialized;
struct power_supply battery;
struct power_supply ac;
};
static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
@@ -130,10 +128,19 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
schedule_work(&wacom->work);
}
extern const struct usb_device_id wacom_ids[];
static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
{
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
power_supply_changed(&wacom->battery);
}
extern const struct hid_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features);
int wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac);
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac);
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -46,6 +46,7 @@
/* wacom data packet report IDs */
#define WACOM_REPORT_PENABLED 2
#define WACOM_REPORT_PENABLED_BT 3
#define WACOM_REPORT_INTUOSREAD 5
#define WACOM_REPORT_INTUOSWRITE 6
#define WACOM_REPORT_INTUOSPAD 12
@@ -68,10 +69,12 @@
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
#define WACOM_QUIRK_NO_INPUT 0x0004
#define WACOM_QUIRK_MONITOR 0x0008
#define WACOM_QUIRK_BATTERY 0x0010
enum {
PENPARTNER = 0,
GRAPHIRE,
GRAPHIRE_BT,
WACOM_G4,
PTU,
PL,
@@ -83,6 +86,7 @@ enum {
INTUOS3L,
INTUOS4S,
INTUOS4,
INTUOS4WL,
INTUOS4L,
INTUOS5S,
INTUOS5,
@@ -114,7 +118,6 @@ enum {
struct wacom_features {
const char *name;
int pktlen;
int x_max;
int y_max;
int pressure_max;
@@ -127,8 +130,8 @@ struct wacom_features {
int device_type;
int x_phy;
int y_phy;
unsigned char unit;
unsigned char unitExpo;
unsigned unit;
int unitExpo;
int x_fuzz;
int y_fuzz;
int pressure_fuzz;
@@ -137,6 +140,9 @@ struct wacom_features {
unsigned touch_max;
int oVid;
int oPid;
int pktlen;
bool check_for_hid_type;
int hid_type;
};
struct wacom_shared {
@@ -150,16 +156,24 @@ struct wacom_shared {
struct wacom_wac {
char name[WACOM_NAME_MAX];
unsigned char *data;
char pad_name[WACOM_NAME_MAX];
char bat_name[WACOM_NAME_MAX];
char ac_name[WACOM_NAME_MAX];
unsigned char data[WACOM_PKGLEN_MAX];
int tool[2];
int id[2];
__u32 serial[2];
struct wacom_features features;
struct wacom_shared *shared;
struct input_dev *input;
struct input_dev *pad_input;
int pid;
int battery_capacity;
int num_contacts_left;
int bat_charging;
int ps_connected;
u8 bt_features;
u8 bt_high_speed;
};
#endif
+10
View File
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
config KEYBOARD_CAP1106
tristate "Microchip CAP1106 touch sensor"
depends on OF && I2C
select REGMAP_I2C
help
Say Y here to enable the CAP1106 touch sensor driver.
To compile this driver as a module, choose M here: the
module will be called cap1106.
endif
+1
View File
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_CAP1106) += cap1106.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
+335
View File
@@ -0,0 +1,335 @@
/*
* Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
*
* http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
*
* (c) 2014 Daniel Mack <linux@zonque.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#define CAP1106_REG_MAIN_CONTROL 0x00
#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6)
#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
#define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4)
#define CAP1106_REG_GENERAL_STATUS 0x02
#define CAP1106_REG_SENSOR_INPUT 0x03
#define CAP1106_REG_NOISE_FLAG_STATUS 0x0a
#define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X))
#define CAP1106_REG_SENSITIVITY_CONTROL 0x1f
#define CAP1106_REG_CONFIG 0x20
#define CAP1106_REG_SENSOR_ENABLE 0x21
#define CAP1106_REG_SENSOR_CONFIG 0x22
#define CAP1106_REG_SENSOR_CONFIG2 0x23
#define CAP1106_REG_SAMPLING_CONFIG 0x24
#define CAP1106_REG_CALIBRATION 0x25
#define CAP1106_REG_INT_ENABLE 0x26
#define CAP1106_REG_REPEAT_RATE 0x28
#define CAP1106_REG_MT_CONFIG 0x2a
#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
#define CAP1106_REG_MT_PATTERN 0x2d
#define CAP1106_REG_RECALIB_CONFIG 0x2f
#define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X))
#define CAP1106_REG_SENSOR_NOISE_THRESH 0x38
#define CAP1106_REG_STANDBY_CHANNEL 0x40
#define CAP1106_REG_STANDBY_CONFIG 0x41
#define CAP1106_REG_STANDBY_SENSITIVITY 0x42
#define CAP1106_REG_STANDBY_THRESH 0x43
#define CAP1106_REG_CONFIG2 0x44
#define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))
#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
#define CAP1106_REG_SENSOR_CALIB_LSB2 0xba
#define CAP1106_REG_PRODUCT_ID 0xfd
#define CAP1106_REG_MANUFACTURER_ID 0xfe
#define CAP1106_REG_REVISION 0xff
#define CAP1106_NUM_CHN 6
#define CAP1106_PRODUCT_ID 0x55
#define CAP1106_MANUFACTURER_ID 0x5d
struct cap1106_priv {
struct regmap *regmap;
struct input_dev *idev;
/* config */
unsigned int keycodes[CAP1106_NUM_CHN];
};
static const struct reg_default cap1106_reg_defaults[] = {
{ CAP1106_REG_MAIN_CONTROL, 0x00 },
{ CAP1106_REG_GENERAL_STATUS, 0x00 },
{ CAP1106_REG_SENSOR_INPUT, 0x00 },
{ CAP1106_REG_NOISE_FLAG_STATUS, 0x00 },
{ CAP1106_REG_SENSITIVITY_CONTROL, 0x2f },
{ CAP1106_REG_CONFIG, 0x20 },
{ CAP1106_REG_SENSOR_ENABLE, 0x3f },
{ CAP1106_REG_SENSOR_CONFIG, 0xa4 },
{ CAP1106_REG_SENSOR_CONFIG2, 0x07 },
{ CAP1106_REG_SAMPLING_CONFIG, 0x39 },
{ CAP1106_REG_CALIBRATION, 0x00 },
{ CAP1106_REG_INT_ENABLE, 0x3f },
{ CAP1106_REG_REPEAT_RATE, 0x3f },
{ CAP1106_REG_MT_CONFIG, 0x80 },
{ CAP1106_REG_MT_PATTERN_CONFIG, 0x00 },
{ CAP1106_REG_MT_PATTERN, 0x3f },
{ CAP1106_REG_RECALIB_CONFIG, 0x8a },
{ CAP1106_REG_SENSOR_THRESH(0), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(1), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(2), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(3), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(4), 0x40 },
{ CAP1106_REG_SENSOR_THRESH(5), 0x40 },
{ CAP1106_REG_SENSOR_NOISE_THRESH, 0x01 },
{ CAP1106_REG_STANDBY_CHANNEL, 0x00 },
{ CAP1106_REG_STANDBY_CONFIG, 0x39 },
{ CAP1106_REG_STANDBY_SENSITIVITY, 0x02 },
{ CAP1106_REG_STANDBY_THRESH, 0x40 },
{ CAP1106_REG_CONFIG2, 0x40 },
{ CAP1106_REG_SENSOR_CALIB_LSB1, 0x00 },
{ CAP1106_REG_SENSOR_CALIB_LSB2, 0x00 },
};
static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CAP1106_REG_MAIN_CONTROL:
case CAP1106_REG_SENSOR_INPUT:
case CAP1106_REG_SENOR_DELTA(0):
case CAP1106_REG_SENOR_DELTA(1):
case CAP1106_REG_SENOR_DELTA(2):
case CAP1106_REG_SENOR_DELTA(3):
case CAP1106_REG_SENOR_DELTA(4):
case CAP1106_REG_SENOR_DELTA(5):
case CAP1106_REG_PRODUCT_ID:
case CAP1106_REG_MANUFACTURER_ID:
case CAP1106_REG_REVISION:
return true;
}
return false;
}
static const struct regmap_config cap1106_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = CAP1106_REG_REVISION,
.reg_defaults = cap1106_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
.cache_type = REGCACHE_RBTREE,
.volatile_reg = cap1106_volatile_reg,
};
static irqreturn_t cap1106_thread_func(int irq_num, void *data)
{
struct cap1106_priv *priv = data;
unsigned int status;
int ret, i;
/*
* Deassert interrupt. This needs to be done before reading the status
* registers, which will not carry valid values otherwise.
*/
ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
if (ret < 0)
goto out;
ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
if (ret < 0)
goto out;
for (i = 0; i < CAP1106_NUM_CHN; i++)
input_report_key(priv->idev, priv->keycodes[i],
status & (1 << i));
input_sync(priv->idev);
out:
return IRQ_HANDLED;
}
static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep)
{
return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
CAP1106_REG_MAIN_CONTROL_DLSEEP,
sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0);
}
static int cap1106_input_open(struct input_dev *idev)
{
struct cap1106_priv *priv = input_get_drvdata(idev);
return cap1106_set_sleep(priv, false);
}
static void cap1106_input_close(struct input_dev *idev)
{
struct cap1106_priv *priv = input_get_drvdata(idev);
cap1106_set_sleep(priv, true);
}
static int cap1106_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct device *dev = &i2c_client->dev;
struct cap1106_priv *priv;
struct device_node *node;
int i, error, irq, gain = 0;
unsigned int val, rev;
u32 gain32, keycodes[CAP1106_NUM_CHN];
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
error = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
if (error)
return error;
if (val != CAP1106_PRODUCT_ID) {
dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
val, CAP1106_PRODUCT_ID);
return -ENODEV;
}
error = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
if (error)
return error;
if (val != CAP1106_MANUFACTURER_ID) {
dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
val, CAP1106_MANUFACTURER_ID);
return -ENODEV;
}
error = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
if (error < 0)
return error;
dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
i2c_set_clientdata(i2c_client, priv);
node = dev->of_node;
if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
if (is_power_of_2(gain32) && gain32 <= 8)
gain = ilog2(gain32);
else
dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
}
BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes));
/* Provide some useful defaults */
for (i = 0; i < ARRAY_SIZE(keycodes); i++)
keycodes[i] = KEY_A + i;
of_property_read_u32_array(node, "linux,keycodes",
keycodes, ARRAY_SIZE(keycodes));
for (i = 0; i < ARRAY_SIZE(keycodes); i++)
priv->keycodes[i] = keycodes[i];
error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
if (error)
return error;
/* Disable autorepeat. The Linux input system has its own handling. */
error = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
if (error)
return error;
priv->idev = devm_input_allocate_device(dev);
if (!priv->idev)
return -ENOMEM;
priv->idev->name = "CAP1106 capacitive touch sensor";
priv->idev->id.bustype = BUS_I2C;
priv->idev->evbit[0] = BIT_MASK(EV_KEY);
if (of_property_read_bool(node, "autorepeat"))
__set_bit(EV_REP, priv->idev->evbit);
for (i = 0; i < CAP1106_NUM_CHN; i++)
__set_bit(priv->keycodes[i], priv->idev->keybit);
priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
priv->idev->id.product = CAP1106_PRODUCT_ID;
priv->idev->id.version = rev;
priv->idev->open = cap1106_input_open;
priv->idev->close = cap1106_input_close;
input_set_drvdata(priv->idev, priv);
/*
* Put the device in deep sleep mode for now.
* ->open() will bring it back once the it is actually needed.
*/
cap1106_set_sleep(priv, true);
error = input_register_device(priv->idev);
if (error)
return error;
irq = irq_of_parse_and_map(node, 0);
if (!irq) {
dev_err(dev, "Unable to parse or map IRQ\n");
return -ENXIO;
}
error = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
IRQF_ONESHOT, dev_name(dev), priv);
if (error)
return error;
return 0;
}
static const struct of_device_id cap1106_dt_ids[] = {
{ .compatible = "microchip,cap1106", },
{}
};
MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
static const struct i2c_device_id cap1106_i2c_ids[] = {
{ "cap1106", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
static struct i2c_driver cap1106_i2c_driver = {
.driver = {
.name = "cap1106",
.owner = THIS_MODULE,
.of_match_table = cap1106_dt_ids,
},
.id_table = cap1106_i2c_ids,
.probe = cap1106_i2c_probe,
};
module_i2c_driver(cap1106_i2c_driver);
MODULE_ALIAS("platform:cap1106");
MODULE_DESCRIPTION("Microchip CAP1106 driver");
MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
MODULE_LICENSE("GPL v2");

Some files were not shown because too many files have changed in this diff Show More