Commit 99380825 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Merge branch 'next' into for-linus

Conflicts:
	drivers/input/tablet/wacom_sys.c
parents 10ce3cc9 131c713f
......@@ -159,11 +159,4 @@ struct kbd_platform_data {
unsigned int mode;
};
/* This function is used to set platform data field of pdev->dev */
static inline void
kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data)
{
pdev->dev.platform_data = data;
}
#endif /* __PLAT_KEYBOARD_H */
......@@ -108,6 +108,9 @@ static int __init amijoy_init(void)
int i, j;
int err;
if (!MACH_IS_AMIGA)
return -ENODEV;
for (i = 0; i < 2; i++) {
if (!amijoy[i])
continue;
......
This diff is collapsed.
......@@ -630,6 +630,7 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
if (!np)
return NULL;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver.
*
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
* Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation.
* Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -55,6 +55,16 @@
#define FSP_BIT_FIX_HSCR BIT(5)
#define FSP_BIT_DRAG_LOCK BIT(6)
#define FSP_REG_SWC1 (0x90)
#define FSP_BIT_SWC1_EN_ABS_1F BIT(0)
#define FSP_BIT_SWC1_EN_GID BIT(1)
#define FSP_BIT_SWC1_EN_ABS_2F BIT(2)
#define FSP_BIT_SWC1_EN_FUP_OUT BIT(3)
#define FSP_BIT_SWC1_EN_ABS_CON BIT(4)
#define FSP_BIT_SWC1_GST_GRP0 BIT(5)
#define FSP_BIT_SWC1_GST_GRP1 BIT(6)
#define FSP_BIT_SWC1_BX_COMPAT BIT(7)
/* Finger-sensing Pad packet formating related definitions */
/* absolute packet type */
......@@ -64,12 +74,32 @@
#define FSP_PKT_TYPE_NORMAL_OPC (0x03)
#define FSP_PKT_TYPE_SHIFT (6)
/* bit definitions for the first byte of report packet */
#define FSP_PB0_LBTN BIT(0)
#define FSP_PB0_RBTN BIT(1)
#define FSP_PB0_MBTN BIT(2)
#define FSP_PB0_MFMC_FGR2 FSP_PB0_MBTN
#define FSP_PB0_MUST_SET BIT(3)
#define FSP_PB0_PHY_BTN BIT(4)
#define FSP_PB0_MFMC BIT(5)
/* hardware revisions */
#define FSP_VER_STL3888_A4 (0xC1)
#define FSP_VER_STL3888_B0 (0xD0)
#define FSP_VER_STL3888_B1 (0xD1)
#define FSP_VER_STL3888_B2 (0xD2)
#define FSP_VER_STL3888_C0 (0xE0)
#define FSP_VER_STL3888_C1 (0xE1)
#define FSP_VER_STL3888_D0 (0xE2)
#define FSP_VER_STL3888_D1 (0xE3)
#define FSP_VER_STL3888_E0 (0xE4)
#ifdef __KERNEL__
struct fsp_data {
unsigned char ver; /* hardware version */
unsigned char rev; /* hardware revison */
unsigned char buttons; /* Number of buttons */
unsigned int buttons; /* Number of buttons */
unsigned int flags;
#define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */
......@@ -78,6 +108,7 @@ struct fsp_data {
unsigned char last_reg; /* Last register we requested read from */
unsigned char last_val;
unsigned int last_mt_fgr; /* Last seen finger(multitouch) */
};
#ifdef CONFIG_MOUSE_PS2_SENTELIC
......
......@@ -76,6 +76,7 @@ config TABLET_USB_KBTAB
config TABLET_USB_WACOM
tristate "Wacom Intuos/Graphire tablet support (USB)"
depends on USB_ARCH_HAS_HCD
select POWER_SUPPLY
select USB
select NEW_LEDS
select LEDS_CLASS
......
......@@ -88,6 +88,7 @@
#include <linux/mod_devicetable.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/power_supply.h>
#include <asm/unaligned.h>
/*
......@@ -112,6 +113,7 @@ struct wacom {
struct urb *irq;
struct wacom_wac wacom_wac;
struct mutex lock;
struct work_struct work;
bool open;
char phys[32];
struct wacom_led {
......@@ -120,8 +122,15 @@ struct wacom {
u8 hlv; /* status led brightness button pressed (1..127) */
u8 img_lum; /* OLED matrix display brightness */
} led;
struct power_supply battery;
};
static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
{
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
schedule_work(&wacom->work);
}
extern const struct usb_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
......
......@@ -167,6 +167,19 @@ static void wacom_close(struct input_dev *dev)
usb_autopm_put_interface(wacom->intf);
}
/*
* Static values for max X/Y and resolution of Pen interface is stored in
* features. This mean physical size of active area can be computed.
* This is useful to do when Pen and Touch have same active area of tablet.
* This means for Touch device, we only need to find max X/Y value and we
* have enough information to compute resolution of touch.
*/
static void wacom_set_phy_from_res(struct wacom_features *features)
{
features->x_phy = (features->x_max * 100) / features->x_resolution;
features->y_phy = (features->y_max * 100) / features->y_resolution;
}
static int wacom_parse_logical_collection(unsigned char *report,
struct wacom_features *features)
{
......@@ -178,15 +191,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
features->device_type = BTN_TOOL_FINGER;
/*
* Stylus and Touch have same active area
* so compute physical size based on stylus
* data before its overwritten.
*/
features->x_phy =
(features->x_max * 100) / features->x_resolution;
features->y_phy =
(features->y_max * 100) / features->y_resolution;
wacom_set_phy_from_res(features);
features->x_max = features->y_max =
get_unaligned_le16(&report[10]);
......@@ -422,6 +427,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
report_id, rep_data, 4, 1);
} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
} else if (features->type != TABLETPC &&
features->type != WIRELESS &&
features->device_type == BTN_TOOL_PEN) {
do {
rep_data[0] = 2;
......@@ -454,6 +460,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
features->pressure_fuzz = 0;
features->distance_fuzz = 0;
/*
* The wireless device HID is basic and layout conflicts with
* other tablets (monitor and touch interface can look like pen).
* Skip the query for this type and modify defaults based on
* interface number.
*/
if (features->type == WIRELESS) {
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
features->device_type = 0;
} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
features->device_type = BTN_TOOL_DOUBLETAP;
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
}
}
/* only Tablet PCs and Bamboo P&T need to retrieve the info */
if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
(features->type != BAMBOO_PT))
......@@ -822,6 +843,152 @@ static void wacom_destroy_leds(struct wacom *wacom)
}
}
static enum power_supply_property wacom_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY
};
static int wacom_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct wacom *wacom = container_of(psy, struct wacom, battery);
int ret = 0;
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY:
val->intval =
wacom->wacom_wac.battery_capacity * 100 / 31;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int wacom_initialize_battery(struct wacom *wacom)
{
int error = 0;
if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
wacom->battery.properties = wacom_battery_props;
wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wacom->battery.get_property = wacom_battery_get_property;
wacom->battery.name = "wacom_battery";
wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wacom->battery.use_for_apm = 0;
error = power_supply_register(&wacom->usbdev->dev,
&wacom->battery);
}
return error;
}
static void wacom_destroy_battery(struct wacom *wacom)
{
if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR)
power_supply_unregister(&wacom->battery);
}
static int wacom_register_input(struct wacom *wacom)
{
struct input_dev *input_dev;
struct usb_interface *intf = wacom->intf;
struct usb_device *dev = interface_to_usbdev(intf);
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
int error;
input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
input_dev->name = wacom_wac->name;
input_dev->dev.parent = &intf->dev;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
usb_to_input_id(dev, &input_dev->id);
input_set_drvdata(input_dev, wacom);
wacom_wac->input = input_dev;
wacom_setup_input_capabilities(input_dev, wacom_wac);
error = input_register_device(input_dev);
if (error) {
input_free_device(input_dev);
wacom_wac->input = NULL;
}
return error;
}
static void wacom_wireless_work(struct work_struct *work)
{
struct wacom *wacom = container_of(work, struct wacom, work);
struct usb_device *usbdev = wacom->usbdev;
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
/*
* Regardless if this is a disconnect or a new tablet,
* remove any existing input devices.
*/
/* Stylus interface */
wacom = usb_get_intfdata(usbdev->config->interface[1]);
if (wacom->wacom_wac.input)
input_unregister_device(wacom->wacom_wac.input);
wacom->wacom_wac.input = 0;
/* Touch interface */
wacom = usb_get_intfdata(usbdev->config->interface[2]);
if (wacom->wacom_wac.input)
input_unregister_device(wacom->wacom_wac.input);
wacom->wacom_wac.input = 0;
if (wacom_wac->pid == 0) {
printk(KERN_INFO "wacom: wireless tablet disconnected\n");
} else {
const struct usb_device_id *id = wacom_ids;
printk(KERN_INFO
"wacom: wireless tablet connected with PID %x\n",
wacom_wac->pid);
while (id->match_flags) {
if (id->idVendor == USB_VENDOR_ID_WACOM &&
id->idProduct == wacom_wac->pid)
break;
id++;
}
if (!id->match_flags) {
printk(KERN_INFO
"wacom: ignorning unknown PID.\n");
return;
}
/* Stylus interface */
wacom = usb_get_intfdata(usbdev->config->interface[1]);
wacom_wac = &wacom->wacom_wac;
wacom_wac->features =
*((struct wacom_features *)id->driver_info);
wacom_wac->features.device_type = BTN_TOOL_PEN;
wacom_register_input(wacom);
/* Touch interface */
wacom = usb_get_intfdata(usbdev->config->interface[2]);
wacom_wac = &wacom->wacom_wac;
wacom_wac->features =
*((struct wacom_features *)id->driver_info);
wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
wacom_wac->features.device_type = BTN_TOOL_FINGER;
wacom_set_phy_from_res(&wacom_wac->features);
wacom_wac->features.x_max = wacom_wac->features.y_max = 4096;
wacom_register_input(wacom);
}
}
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
......@@ -829,18 +996,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct wacom *wacom;
struct wacom_wac *wacom_wac;
struct wacom_features *features;
struct input_dev *input_dev;
int error;
if (!id->driver_info)
return -EINVAL;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
input_dev = input_allocate_device();
if (!wacom || !input_dev) {
error = -ENOMEM;
goto fail1;
}
wacom_wac = &wacom->wacom_wac;
wacom_wac->features = *((struct wacom_features *)id->driver_info);
......@@ -866,11 +1027,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->usbdev = dev;
wacom->intf = intf;
mutex_init(&wacom->lock);
INIT_WORK(&wacom->work, wacom_wireless_work);
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
wacom_wac->input = input_dev;
endpoint = &intf->cur_altsetting->endpoint[0].desc;
/* Retrieve the physical and logical size for OEM devices */
......@@ -894,15 +1054,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
goto fail3;
}
input_dev->name = wacom_wac->name;
input_dev->dev.parent = &intf->dev;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
usb_to_input_id(dev, &input_dev->id);
input_set_drvdata(input_dev, wacom);
wacom_setup_input_capabilities(input_dev, wacom_wac);
usb_fill_int_urb(wacom->irq, dev,
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom_wac->data, features->pktlen,
......@@ -914,22 +1065,34 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
if (error)
goto fail4;
error = input_register_device(input_dev);
error = wacom_initialize_battery(wacom);
if (error)
goto fail5;
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
error = wacom_register_input(wacom);
if (error)
goto fail6;
}
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(intf, features);
usb_set_intfdata(intf, wacom);
if (features->quirks & WACOM_QUIRK_MONITOR) {
if (usb_submit_urb(wacom->irq, GFP_KERNEL))
goto fail5;
}
return 0;
fail6: wacom_destroy_battery(wacom);
fail5: wacom_destroy_leds(wacom);
fail4: wacom_remove_shared_data(wacom_wac);
fail3: usb_free_urb(wacom->irq);
fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
fail1: input_free_device(input_dev);
kfree(wacom);
fail1: kfree(wacom);
return error;
}
......@@ -940,7 +1103,10 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_kill_urb(wacom->irq);
cancel_work_sync(&wacom->work);
if (wacom->wacom_wac.input)
input_unregister_device(wacom->wacom_wac.input);
wacom_destroy_battery(wacom);
wacom_destroy_leds(wacom);
usb_free_urb(wacom->irq);
usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
......@@ -972,7 +1138,8 @@ static int wacom_resume(struct usb_interface *intf)
wacom_query_tablet_data(intf, features);
wacom_led_control(wacom);
if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR)
&& usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
rv = -EIO;
mutex_unlock(&wacom->lock);
......
......@@ -1044,6 +1044,35 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
return 0;
}
static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
{
unsigned char *data = wacom->data;
int connected;
if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80)
return 0;
connected = data[1] & 0x01;
if (connected) {
int pid, battery;
pid = get_unaligned_be16(&data[6]);
battery = data[5] & 0x3f;
if (wacom->pid != pid) {
wacom->pid = pid;
wacom_schedule_work(wacom);
}
wacom->battery_capacity = battery;
} else if (wacom->pid != 0) {
/* disconnected while previously connected */
wacom->pid = 0;
wacom_schedule_work(wacom);
wacom->battery_capacity = 0;
}
return 0;
}
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
{
bool sync;
......@@ -1094,6 +1123,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
sync = wacom_bpt_irq(wacom_wac, len);
break;
case WIRELESS:
sync = wacom_wireless_irq(wacom_wac, len);
break;
default:
sync = false;
break;
......@@ -1155,7 +1188,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
/* these device have multiple inputs */
if (features->type == TABLETPC || features->type == TABLETPC2FG ||
features->type == BAMBOO_PT)
features->type == BAMBOO_PT || features->type == WIRELESS)
features->quirks |= WACOM_QUIRK_MULTI_INPUT;
/* quirk for bamboo touch with 2 low res touches */
......@@ -1167,6 +1200,16 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features->y_fuzz <<= 5;
features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
}
if (features->type == WIRELESS) {
/* monitor never has input and pen/touch have delayed create */
features->quirks |= WACOM_QUIRK_NO_INPUT;
/* must be monitor interface if no device_type set */
if (!features->device_type)
features->quirks |= WACOM_QUIRK_MONITOR;
}
}
static unsigned int wacom_calculate_touch_res(unsigned int logical_max,
......@@ -1640,6 +1683,9 @@ static const struct wacom_features wacom_features_0xEC =
static const struct wacom_features wacom_features_0x47 =
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x84 =
{ "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0,
0, WIRELESS, 0, 0 };
static const struct wacom_features wacom_features_0xD0 =
{ "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
......@@ -1766,6 +1812,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ USB_DEVICE_WACOM(0x84) },
{ USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) },
......
......@@ -24,6 +24,7 @@
#define WACOM_PKGLEN_BBTOUCH 20
#define WACOM_PKGLEN_BBTOUCH3 64
#define WACOM_PKGLEN_BBPEN 10
#define WACOM_PKGLEN_WIRELESS 32
/* device IDs */
#define STYLUS_DEVICE_ID 0x02
......@@ -45,6 +46,8 @@
/* device quirks */
#define WACOM_QUIRK_MULTI_INPUT 0x0001
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
#define WACOM_QUIRK_NO_INPUT 0x0004
#define WACOM_QUIRK_MONITOR 0x0008
enum {
PENPARTNER = 0,
......@@ -54,6 +57,7 @@ enum {
PL,
DTU,
BAMBOO_PT,
WIRELESS,
INTUOS,
INTUOS3S,
INTUOS3,
......@@ -107,6 +111,8 @@ struct wacom_wac {
struct wacom_features features;
struct wacom_shared *shared;
struct input_dev *input;
int pid;
int battery_capacity;
};
#endif
......@@ -6,7 +6,7 @@ struct device;
struct gpio_keys_button {
/* Configuration parameters */
unsigned int code; /* input event code (KEY_*, SW_*) */
int gpio;
int gpio; /* -1 if this key does not support gpio */
int active_low;
const char *desc;
unsigned int type; /* input event type (EV_KEY, EV_SW, EV_ABS) */
......@@ -14,6 +14,7 @@ struct gpio_keys_button {
int debounce_interval; /* debounce ticks interval in msecs */
bool can_disable;
int value; /* axis value for EV_ABS */
unsigned int irq; /* Irq number in case of interrupt keys */
};
struct gpio_keys_platform_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment