mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Linux 3.11
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQEcBAABAgAGBQJSJPkeAAoJEHm+PkMAQRiGVWMH/jo5f01Ra7G4/CYS59K+AlBQ /oWL3W81r5MORlsMxwUwGtJ3sZ7UulKwiDrluWeOkz2+/9SmoHoUfkpbByq1bSIV y0eqhmjtkHQZz5radJIHeyz1gJIICBIgAM0l45j8SpK4n9EXRcjLSZjdjAkPzxZp qZpfxKhVSTu79m96bud7F+HrboHDQEyhD9zqdSi4xPQNnOmTc7K3tvui9AB3rMbV ablM3C+LqBYjZx+pKS/rOdfATxZvtU392HU53XTALt6VD1e8alMmhmpe0I9Zxvjv scsB6hfRkevfe7VaK3aVoDnQnLKd61yxs+/XdzTtkWPbVGp+kiuFUdDv/5y2r1g= =7Xf6 -----END PGP SIGNATURE----- Merge tag 'v3.11' into next Merge with mainline to bring in sync changes to cyttsp4 driver.
This commit is contained in:
commit
4ba25a496f
9703 changed files with 736937 additions and 287299 deletions
|
|
@ -137,7 +137,7 @@ static const struct xpad_device {
|
|||
{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX },
|
||||
{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", XTYPE_XBOX360 },
|
||||
{ 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 },
|
||||
|
|
@ -167,6 +167,7 @@ static const struct xpad_device {
|
|||
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x1689, 0xfd01, "Razer Onza Classic Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
|
||||
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
|
||||
|
|
|
|||
|
|
@ -441,6 +441,7 @@ config KEYBOARD_TEGRA
|
|||
|
||||
config KEYBOARD_OPENCORES
|
||||
tristate "OpenCores Keyboard Controller"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Say Y here if you want to use the OpenCores Keyboard Controller
|
||||
http://www.opencores.org/project,keyboardcontroller
|
||||
|
|
|
|||
|
|
@ -206,33 +206,6 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/* Clear any keys in the buffer */
|
||||
static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
|
||||
{
|
||||
uint8_t old_state[ckdev->cols];
|
||||
uint8_t new_state[ckdev->cols];
|
||||
unsigned long duration;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
* Keep reading until we see that the scan state does not change.
|
||||
* That indicates that we are done.
|
||||
*
|
||||
* Assume that the EC keyscan buffer is at most 32 deep.
|
||||
*/
|
||||
duration = jiffies;
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
for (i = 1; !ret && i < 32; i++) {
|
||||
memcpy(old_state, new_state, sizeof(old_state));
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
if (0 == memcmp(old_state, new_state, sizeof(old_state)))
|
||||
break;
|
||||
}
|
||||
duration = jiffies - duration;
|
||||
dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
|
||||
jiffies_to_usecs(duration));
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
|
||||
|
|
@ -299,6 +272,33 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Clear any keys in the buffer */
|
||||
static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
|
||||
{
|
||||
uint8_t old_state[ckdev->cols];
|
||||
uint8_t new_state[ckdev->cols];
|
||||
unsigned long duration;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
* Keep reading until we see that the scan state does not change.
|
||||
* That indicates that we are done.
|
||||
*
|
||||
* Assume that the EC keyscan buffer is at most 32 deep.
|
||||
*/
|
||||
duration = jiffies;
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
for (i = 1; !ret && i < 32; i++) {
|
||||
memcpy(old_state, new_state, sizeof(old_state));
|
||||
ret = cros_ec_keyb_get_state(ckdev, new_state);
|
||||
if (0 == memcmp(old_state, new_state, sizeof(old_state)))
|
||||
break;
|
||||
}
|
||||
duration = jiffies - duration;
|
||||
dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
|
||||
jiffies_to_usecs(duration));
|
||||
}
|
||||
|
||||
static int cros_ec_keyb_resume(struct device *dev)
|
||||
{
|
||||
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/input/samsung-keypad.h>
|
||||
|
||||
|
|
@ -79,10 +78,6 @@ struct samsung_keypad {
|
|||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
unsigned int row_state[SAMSUNG_MAX_COLS];
|
||||
#ifdef CONFIG_OF
|
||||
int row_gpios[SAMSUNG_MAX_ROWS];
|
||||
int col_gpios[SAMSUNG_MAX_COLS];
|
||||
#endif
|
||||
unsigned short keycodes[];
|
||||
};
|
||||
|
||||
|
|
@ -304,45 +299,6 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
|
|||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static void samsung_keypad_parse_dt_gpio(struct device *dev,
|
||||
struct samsung_keypad *keypad)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
int gpio, error, row, col;
|
||||
|
||||
for (row = 0; row < keypad->rows; row++) {
|
||||
gpio = of_get_named_gpio(np, "row-gpios", row);
|
||||
keypad->row_gpios[row] = gpio;
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(dev, "keypad row[%d]: invalid gpio %d\n",
|
||||
row, gpio);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = devm_gpio_request(dev, gpio, "keypad-row");
|
||||
if (error)
|
||||
dev_err(dev,
|
||||
"keypad row[%d] gpio request failed: %d\n",
|
||||
row, error);
|
||||
}
|
||||
|
||||
for (col = 0; col < keypad->cols; col++) {
|
||||
gpio = of_get_named_gpio(np, "col-gpios", col);
|
||||
keypad->col_gpios[col] = gpio;
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(dev, "keypad column[%d]: invalid gpio %d\n",
|
||||
col, gpio);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = devm_gpio_request(dev, gpio, "keypad-col");
|
||||
if (error)
|
||||
dev_err(dev,
|
||||
"keypad column[%d] gpio request failed: %d\n",
|
||||
col, error);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static
|
||||
struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev)
|
||||
|
|
@ -424,15 +380,11 @@ static int samsung_keypad_probe(struct platform_device *pdev)
|
|||
keypad->stopped = true;
|
||||
init_waitqueue_head(&keypad->wait);
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
#ifdef CONFIG_OF
|
||||
samsung_keypad_parse_dt_gpio(&pdev->dev, keypad);
|
||||
if (pdev->dev.of_node)
|
||||
keypad->type = of_device_is_compatible(pdev->dev.of_node,
|
||||
"samsung,s5pv210-keypad");
|
||||
#endif
|
||||
} else {
|
||||
else
|
||||
keypad->type = platform_get_device_id(pdev)->driver_data;
|
||||
}
|
||||
|
||||
input_dev->name = pdev->name;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ static void da9055_onkey_query(struct da9055_onkey *onkey)
|
|||
} else {
|
||||
key_stat &= DA9055_NOKEY_STS;
|
||||
/*
|
||||
* Onkey status bit is cleared when onkey button is relased.
|
||||
* Onkey status bit is cleared when onkey button is released.
|
||||
*/
|
||||
if (!key_stat) {
|
||||
input_report_key(onkey->input, KEY_POWER, 0);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
|
||||
/* MacbookAir6,2 (unibody, June 2013) */
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0291
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0292
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0293
|
||||
|
||||
#define BCM5974_DEVICE(prod) { \
|
||||
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
||||
|
|
@ -145,6 +149,10 @@ static const struct usb_device_id bcm5974_table[] = {
|
|||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
|
||||
/* MacbookAir6,2 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
|
||||
/* Terminating entry */
|
||||
{}
|
||||
};
|
||||
|
|
@ -172,15 +180,18 @@ struct bt_data {
|
|||
/* trackpad header types */
|
||||
enum tp_type {
|
||||
TYPE1, /* plain trackpad */
|
||||
TYPE2 /* button integrated in trackpad */
|
||||
TYPE2, /* button integrated in trackpad */
|
||||
TYPE3 /* additional header fields since June 2013 */
|
||||
};
|
||||
|
||||
/* trackpad finger data offsets, le16-aligned */
|
||||
#define FINGER_TYPE1 (13 * sizeof(__le16))
|
||||
#define FINGER_TYPE2 (15 * sizeof(__le16))
|
||||
#define FINGER_TYPE3 (19 * sizeof(__le16))
|
||||
|
||||
/* trackpad button data offsets */
|
||||
#define BUTTON_TYPE2 15
|
||||
#define BUTTON_TYPE3 23
|
||||
|
||||
/* list of device capability bits */
|
||||
#define HAS_INTEGRATED_BUTTON 1
|
||||
|
|
@ -400,6 +411,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||
{ SN_COORD, -150, 6730 },
|
||||
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
|
||||
},
|
||||
{
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING8_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
|
||||
HAS_INTEGRATED_BUTTON,
|
||||
0, sizeof(struct bt_data),
|
||||
0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS,
|
||||
{ SN_PRESSURE, 0, 300 },
|
||||
{ SN_WIDTH, 0, 2048 },
|
||||
{ SN_COORD, -4620, 5140 },
|
||||
{ SN_COORD, -150, 6600 },
|
||||
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
@ -557,6 +581,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
input_report_key(input, BTN_LEFT, ibt);
|
||||
}
|
||||
|
||||
if (c->tp_type == TYPE3)
|
||||
input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]);
|
||||
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
|
|
@ -572,9 +599,14 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
|
||||
static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
|
||||
{
|
||||
char *data = kmalloc(8, GFP_KERNEL);
|
||||
int retval = 0, size;
|
||||
char *data;
|
||||
|
||||
/* Type 3 does not require a mode switch */
|
||||
if (dev->cfg.tp_type == TYPE3)
|
||||
return 0;
|
||||
|
||||
data = kmalloc(8, GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(&dev->intf->dev, "out of memory\n");
|
||||
retval = -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -672,6 +672,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
|
|||
*/
|
||||
static int elantech_packet_check_v3(struct psmouse *psmouse)
|
||||
{
|
||||
struct elantech_data *etd = psmouse->private;
|
||||
const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
|
||||
unsigned char *packet = psmouse->packet;
|
||||
|
||||
|
|
@ -682,19 +683,48 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
|
|||
if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
|
||||
return PACKET_DEBOUNCE;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
|
||||
return PACKET_V3_HEAD;
|
||||
/*
|
||||
* If the hardware flag 'crc_enabled' is set the packets have
|
||||
* different signatures.
|
||||
*/
|
||||
if (etd->crc_enabled) {
|
||||
if ((packet[3] & 0x09) == 0x08)
|
||||
return PACKET_V3_HEAD;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
|
||||
return PACKET_V3_TAIL;
|
||||
if ((packet[3] & 0x09) == 0x09)
|
||||
return PACKET_V3_TAIL;
|
||||
} else {
|
||||
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
|
||||
return PACKET_V3_HEAD;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
|
||||
return PACKET_V3_TAIL;
|
||||
}
|
||||
|
||||
return PACKET_UNKNOWN;
|
||||
}
|
||||
|
||||
static int elantech_packet_check_v4(struct psmouse *psmouse)
|
||||
{
|
||||
struct elantech_data *etd = psmouse->private;
|
||||
unsigned char *packet = psmouse->packet;
|
||||
unsigned char packet_type = packet[3] & 0x03;
|
||||
bool sanity_check;
|
||||
|
||||
/*
|
||||
* Sanity check based on the constant bits of a packet.
|
||||
* The constant bits change depending on the value of
|
||||
* the hardware flag 'crc_enabled' but are the same for
|
||||
* every packet, regardless of the type.
|
||||
*/
|
||||
if (etd->crc_enabled)
|
||||
sanity_check = ((packet[3] & 0x08) == 0x00);
|
||||
else
|
||||
sanity_check = ((packet[0] & 0x0c) == 0x04 &&
|
||||
(packet[3] & 0x1c) == 0x10);
|
||||
|
||||
if (!sanity_check)
|
||||
return PACKET_UNKNOWN;
|
||||
|
||||
switch (packet_type) {
|
||||
case 0:
|
||||
|
|
@ -1313,6 +1343,12 @@ static int elantech_set_properties(struct elantech_data *etd)
|
|||
etd->reports_pressure = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The signatures of v3 and v4 packets change depending on the
|
||||
* value of this hardware flag.
|
||||
*/
|
||||
etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ struct elantech_data {
|
|||
bool paritycheck;
|
||||
bool jumpy_cursor;
|
||||
bool reports_pressure;
|
||||
bool crc_enabled;
|
||||
unsigned char hw_version;
|
||||
unsigned int fw_version;
|
||||
unsigned int single_finger_reports;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ config SERIO_I8042
|
|||
tristate "i8042 PC Keyboard controller" if EXPERT || !X86
|
||||
default y
|
||||
depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
|
||||
(!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390
|
||||
(!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \
|
||||
!ARC
|
||||
help
|
||||
i8042 is the chip over which the standard AT keyboard and PS/2
|
||||
mouse are connected to the computer. If you use these devices,
|
||||
|
|
@ -205,6 +206,7 @@ config SERIO_XILINX_XPS_PS2
|
|||
|
||||
config SERIO_ALTERA_PS2
|
||||
tristate "Altera UP PS/2 controller"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Say Y here if you have Altera University Program PS/2 ports.
|
||||
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
|
|||
case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
|
||||
case 0x160802: /* Cintiq 13HD Pro Pen */
|
||||
case 0x180802: /* DTH2242 Pen */
|
||||
case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
|
||||
wacom->tool[idx] = BTN_TOOL_PEN;
|
||||
break;
|
||||
|
||||
|
|
@ -401,6 +402,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
|
|||
case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
|
||||
case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
|
||||
case 0x18080a: /* DTH2242 Eraser */
|
||||
case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
|
||||
wacom->tool[idx] = BTN_TOOL_RUBBER;
|
||||
break;
|
||||
|
||||
|
|
@ -2099,7 +2101,7 @@ static const struct wacom_features wacom_features_0xDA =
|
|||
{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
.touch_max = 2 };
|
||||
static struct wacom_features wacom_features_0xDB =
|
||||
static const struct wacom_features wacom_features_0xDB =
|
||||
{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
.touch_max = 2 };
|
||||
|
|
@ -2114,6 +2116,12 @@ static const struct wacom_features wacom_features_0xDF =
|
|||
{ "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
|
||||
.touch_max = 16 };
|
||||
static const struct wacom_features wacom_features_0x300 =
|
||||
{ "Wacom Bamboo One S", WACOM_PKGLEN_BBPEN, 14720, 9225, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x301 =
|
||||
{ "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023,
|
||||
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x6004 =
|
||||
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
|
||||
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
|
|
@ -2240,6 +2248,8 @@ const struct usb_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE_WACOM(0x100) },
|
||||
{ USB_DEVICE_WACOM(0x101) },
|
||||
{ USB_DEVICE_WACOM(0x10D) },
|
||||
{ USB_DEVICE_WACOM(0x300) },
|
||||
{ USB_DEVICE_WACOM(0x301) },
|
||||
{ USB_DEVICE_WACOM(0x304) },
|
||||
{ USB_DEVICE_WACOM(0x4001) },
|
||||
{ USB_DEVICE_WACOM(0x47) },
|
||||
|
|
|
|||
|
|
@ -909,6 +909,7 @@ config TOUCHSCREEN_STMPE
|
|||
config TOUCHSCREEN_TPS6507X
|
||||
tristate "TPS6507x based touchscreens"
|
||||
depends on I2C
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have a TPS6507x based touchscreen
|
||||
controller.
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ static int cyttsp4_hw_reset(struct cyttsp4 *cd)
|
|||
*/
|
||||
static int cyttsp4_bits_2_bytes(unsigned int nbits, size_t *max)
|
||||
{
|
||||
*max = 1 << nbits;
|
||||
*max = 1UL << nbits;
|
||||
return (nbits + 7) / 8;
|
||||
}
|
||||
|
||||
|
|
@ -1447,11 +1447,6 @@ static void cyttsp4_watchdog_work(struct work_struct *work)
|
|||
u8 *mode;
|
||||
int retval;
|
||||
|
||||
if (cd == NULL) {
|
||||
dev_err(cd->dev, "%s: NULL context pointer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&cd->system_lock);
|
||||
retval = cyttsp4_load_status_regs(cd);
|
||||
if (retval < 0) {
|
||||
|
|
@ -2027,7 +2022,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
|
|||
if (!cd->xfer_buf) {
|
||||
dev_err(dev, "%s: Error, kzalloc\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto error_alloc_data;
|
||||
goto error_free_cd;
|
||||
}
|
||||
|
||||
/* Initialize device info */
|
||||
|
|
@ -2051,7 +2046,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
|
|||
cd->irq = gpio_to_irq(cd->cpdata->irq_gpio);
|
||||
if (cd->irq < 0) {
|
||||
rc = -EINVAL;
|
||||
goto error_gpio_irq;
|
||||
goto error_free_xfer;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, cd);
|
||||
|
|
@ -2119,7 +2114,9 @@ error_request_irq:
|
|||
if (cd->cpdata->init)
|
||||
cd->cpdata->init(cd->cpdata, 0, dev);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
error_gpio_irq:
|
||||
error_free_xfer:
|
||||
kfree(cd->xfer_buf);
|
||||
error_free_cd:
|
||||
kfree(cd);
|
||||
error_alloc_data:
|
||||
error_no_pdata:
|
||||
|
|
|
|||
|
|
@ -369,9 +369,9 @@ struct cyttsp4 {
|
|||
|
||||
struct cyttsp4_bus_ops {
|
||||
u16 bustype;
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
const void *values);
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
void *values);
|
||||
};
|
||||
|
||||
|
|
@ -448,13 +448,13 @@ enum cyttsp4_event_id {
|
|||
/* y-axis, 0:origin is on top side of panel, 1: bottom */
|
||||
#define CY_PCFG_ORIGIN_Y_MASK 0x80
|
||||
|
||||
static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u8 addr, int size,
|
||||
static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size,
|
||||
void *buf)
|
||||
{
|
||||
return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
}
|
||||
|
||||
static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
|
||||
static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size,
|
||||
const void *buf)
|
||||
{
|
||||
return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
|
|
@ -463,9 +463,9 @@ static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
|
|||
extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
|
||||
struct device *dev, u16 irq, size_t xfer_buf_size);
|
||||
extern int cyttsp4_remove(struct cyttsp4 *ts);
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, const void *values);
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, void *values);
|
||||
extern const struct dev_pm_ops cyttsp4_pm_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
|
||||
|
||||
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
||||
u8 op, u8 reg, u8 *buf, int length)
|
||||
u8 op, u16 reg, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
|
|
@ -63,14 +63,12 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
|
||||
memset(rd_buf, 0, CY_SPI_CMD_BYTES);
|
||||
|
||||
if (reg > 255)
|
||||
wr_buf[0] = op + CY_SPI_A8_BIT;
|
||||
else
|
||||
wr_buf[0] = op;
|
||||
if (op == CY_SPI_WR_OP)
|
||||
wr_buf[1] = reg % 256;
|
||||
if (op == CY_SPI_WR_OP && length > 0)
|
||||
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
|
||||
wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0);
|
||||
if (op == CY_SPI_WR_OP) {
|
||||
wr_buf[1] = reg & 0xFF;
|
||||
if (length > 0)
|
||||
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
|
||||
}
|
||||
|
||||
memset(xfer, 0, sizeof(xfer));
|
||||
spi_message_init(&msg);
|
||||
|
|
@ -130,7 +128,7 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *data)
|
||||
u16 addr, u8 length, void *data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
|
@ -143,7 +141,7 @@ static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *data)
|
||||
u16 addr, u8 length, const void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
|
||||
length);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,15 @@ static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
|
|||
return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
static int cyttsp_handshake(struct cyttsp *ts)
|
||||
{
|
||||
if (ts->pdata->use_hndshk)
|
||||
return ttsp_send_command(ts,
|
||||
ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp_load_bl_regs(struct cyttsp *ts)
|
||||
{
|
||||
memset(&ts->bl_data, 0, sizeof(ts->bl_data));
|
||||
|
|
@ -135,7 +144,7 @@ static int cyttsp_exit_bl_mode(struct cyttsp *ts)
|
|||
memcpy(bl_cmd, bl_command, sizeof(bl_command));
|
||||
if (ts->pdata->bl_keys)
|
||||
memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
|
||||
ts->pdata->bl_keys, sizeof(bl_command));
|
||||
ts->pdata->bl_keys, CY_NUM_BL_KEYS);
|
||||
|
||||
error = ttsp_write_block_data(ts, CY_REG_BASE,
|
||||
sizeof(bl_cmd), bl_cmd);
|
||||
|
|
@ -169,6 +178,10 @@ static int cyttsp_set_operational_mode(struct cyttsp *ts)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
error = cyttsp_handshake(ts);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +203,10 @@ static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
error = cyttsp_handshake(ts);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
|
||||
return -EIO;
|
||||
|
||||
|
|
@ -346,12 +363,9 @@ static irqreturn_t cyttsp_irq(int irq, void *handle)
|
|||
goto out;
|
||||
|
||||
/* provide flow control handshake */
|
||||
if (ts->pdata->use_hndshk) {
|
||||
error = ttsp_send_command(ts,
|
||||
ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
error = cyttsp_handshake(ts);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (unlikely(ts->state == CY_IDLE_STATE))
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ struct cyttsp_xydata {
|
|||
/* TTSP System Information interface definition */
|
||||
struct cyttsp_sysinfo_data {
|
||||
u8 hst_mode;
|
||||
u8 mfg_cmd;
|
||||
u8 mfg_stat;
|
||||
u8 mfg_cmd;
|
||||
u8 cid[3];
|
||||
u8 tt_undef1;
|
||||
u8 uid[8];
|
||||
|
|
@ -112,9 +112,9 @@ struct cyttsp;
|
|||
|
||||
struct cyttsp_bus_ops {
|
||||
u16 bustype;
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
const void *values);
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
void *values);
|
||||
};
|
||||
|
||||
|
|
@ -145,9 +145,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
|
|||
struct device *dev, int irq, size_t xfer_buf_size);
|
||||
void cyttsp_remove(struct cyttsp *ts);
|
||||
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, const void *values);
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, void *values);
|
||||
extern const struct dev_pm_ops cyttsp_pm_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,18 +32,20 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *values)
|
||||
u16 addr, u8 length, void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
u8 client_addr = client->addr | ((addr >> 8) & 0x1);
|
||||
u8 addr_lo = addr & 0xFF;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.addr = client_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &addr,
|
||||
.buf = &addr_lo,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.addr = client_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = length,
|
||||
.buf = values,
|
||||
|
|
@ -60,17 +62,29 @@ int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
|
|||
EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data);
|
||||
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *values)
|
||||
u16 addr, u8 length, const void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
u8 client_addr = client->addr | ((addr >> 8) & 0x1);
|
||||
u8 addr_lo = addr & 0xFF;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client_addr,
|
||||
.flags = 0,
|
||||
.len = length + 1,
|
||||
.buf = xfer_buf,
|
||||
},
|
||||
};
|
||||
int retval;
|
||||
|
||||
xfer_buf[0] = addr;
|
||||
xfer_buf[0] = addr_lo;
|
||||
memcpy(&xfer_buf[1], values, length);
|
||||
|
||||
retval = i2c_master_send(client, xfer_buf, length + 1);
|
||||
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
return retval < 0 ? retval : 0;
|
||||
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#define CY_SPI_BITS_PER_WORD 8
|
||||
|
||||
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
||||
u8 op, u8 reg, u8 *buf, int length)
|
||||
u8 op, u16 reg, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
|
|
@ -126,14 +126,14 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *data)
|
||||
u16 addr, u8 length, void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
|
||||
length);
|
||||
}
|
||||
|
||||
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *data)
|
||||
u16 addr, u8 length, const void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
|
||||
length);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/input/ti_am335x_tsc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/mfd/ti_am335x_tscadc.h>
|
||||
|
||||
|
|
@ -33,6 +34,13 @@
|
|||
#define SEQ_SETTLE 275
|
||||
#define MAX_12BIT ((1 << 12) - 1)
|
||||
|
||||
static const int config_pins[] = {
|
||||
STEPCONFIG_XPP,
|
||||
STEPCONFIG_XNN,
|
||||
STEPCONFIG_YPP,
|
||||
STEPCONFIG_YNN,
|
||||
};
|
||||
|
||||
struct titsc {
|
||||
struct input_dev *input;
|
||||
struct ti_tscadc_dev *mfd_tscadc;
|
||||
|
|
@ -40,7 +48,10 @@ struct titsc {
|
|||
unsigned int wires;
|
||||
unsigned int x_plate_resistance;
|
||||
bool pen_down;
|
||||
int steps_to_configure;
|
||||
int coordinate_readouts;
|
||||
u32 config_inp[4];
|
||||
u32 bit_xp, bit_xn, bit_yp, bit_yn;
|
||||
u32 inp_xp, inp_xn, inp_yp, inp_yn;
|
||||
};
|
||||
|
||||
static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
|
||||
|
|
@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
|
|||
writel(val, tsc->mfd_tscadc->tscadc_base + reg);
|
||||
}
|
||||
|
||||
static int titsc_config_wires(struct titsc *ts_dev)
|
||||
{
|
||||
u32 analog_line[4];
|
||||
u32 wire_order[4];
|
||||
int i, bit_cfg;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
/*
|
||||
* Get the order in which TSC wires are attached
|
||||
* w.r.t. each of the analog input lines on the EVM.
|
||||
*/
|
||||
analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
|
||||
wire_order[i] = ts_dev->config_inp[i] & 0x0F;
|
||||
if (WARN_ON(analog_line[i] > 7))
|
||||
return -EINVAL;
|
||||
if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int an_line;
|
||||
int wi_order;
|
||||
|
||||
an_line = analog_line[i];
|
||||
wi_order = wire_order[i];
|
||||
bit_cfg = config_pins[wi_order];
|
||||
if (bit_cfg == 0)
|
||||
return -EINVAL;
|
||||
switch (wi_order) {
|
||||
case 0:
|
||||
ts_dev->bit_xp = bit_cfg;
|
||||
ts_dev->inp_xp = an_line;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ts_dev->bit_xn = bit_cfg;
|
||||
ts_dev->inp_xn = an_line;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ts_dev->bit_yp = bit_cfg;
|
||||
ts_dev->inp_yp = an_line;
|
||||
break;
|
||||
case 3:
|
||||
ts_dev->bit_yn = bit_cfg;
|
||||
ts_dev->inp_yn = an_line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void titsc_step_config(struct titsc *ts_dev)
|
||||
{
|
||||
unsigned int config;
|
||||
int i, total_steps;
|
||||
|
||||
/* Configure the Step registers */
|
||||
total_steps = 2 * ts_dev->steps_to_configure;
|
||||
int i;
|
||||
int end_step;
|
||||
u32 stepenable;
|
||||
|
||||
config = STEPCONFIG_MODE_HWSYNC |
|
||||
STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_xp;
|
||||
switch (ts_dev->wires) {
|
||||
case 4:
|
||||
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
|
||||
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
|
||||
break;
|
||||
case 5:
|
||||
config |= STEPCONFIG_YNN |
|
||||
STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
|
||||
STEPCONFIG_YPP;
|
||||
config |= ts_dev->bit_yn |
|
||||
STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
|
||||
ts_dev->bit_yp;
|
||||
break;
|
||||
case 8:
|
||||
config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
|
||||
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 1; i <= ts_dev->steps_to_configure; i++) {
|
||||
/* 1 … coordinate_readouts is for X */
|
||||
end_step = ts_dev->coordinate_readouts;
|
||||
for (i = 0; i < end_step; i++) {
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
||||
}
|
||||
|
||||
config = 0;
|
||||
config = STEPCONFIG_MODE_HWSYNC |
|
||||
STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
|
||||
STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_yn |
|
||||
STEPCONFIG_INM_ADCREFM;
|
||||
switch (ts_dev->wires) {
|
||||
case 4:
|
||||
config |= STEPCONFIG_YPP;
|
||||
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
|
||||
break;
|
||||
case 5:
|
||||
config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
|
||||
STEPCONFIG_XNP | STEPCONFIG_YPN;
|
||||
config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
|
||||
ts_dev->bit_xn | ts_dev->bit_yp;
|
||||
break;
|
||||
case 8:
|
||||
config |= STEPCONFIG_YPP;
|
||||
config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
|
||||
/* coordinate_readouts … coordinate_readouts * 2 is for Y */
|
||||
end_step = ts_dev->coordinate_readouts * 2;
|
||||
for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
|
||||
}
|
||||
|
||||
config = 0;
|
||||
/* Charge step configuration */
|
||||
config = STEPCONFIG_XPP | STEPCONFIG_YNN |
|
||||
config = ts_dev->bit_xp | ts_dev->bit_yn |
|
||||
STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
|
||||
STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
|
||||
STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
|
||||
|
||||
titsc_writel(ts_dev, REG_CHARGECONFIG, config);
|
||||
titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
|
||||
|
||||
config = 0;
|
||||
/* Configure to calculate pressure */
|
||||
/* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
|
||||
config = STEPCONFIG_MODE_HWSYNC |
|
||||
STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
|
||||
STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_yp |
|
||||
ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
|
||||
STEPCONFIG_INP(ts_dev->inp_xp);
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
|
||||
STEPCONFIG_OPENDLY);
|
||||
|
||||
config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
|
||||
end_step++;
|
||||
config |= STEPCONFIG_INP(ts_dev->inp_yn);
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
|
||||
STEPCONFIG_OPENDLY);
|
||||
|
||||
titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
|
||||
/* The steps1 … end and bit 0 for TS_Charge */
|
||||
stepenable = (1 << (end_step + 2)) - 1;
|
||||
am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
|
||||
}
|
||||
|
||||
static void titsc_read_coordinates(struct titsc *ts_dev,
|
||||
unsigned int *x, unsigned int *y)
|
||||
u32 *x, u32 *y, u32 *z1, u32 *z2)
|
||||
{
|
||||
unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
|
||||
unsigned int prev_val_x = ~0, prev_val_y = ~0;
|
||||
unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
|
||||
unsigned int read, diff;
|
||||
unsigned int i, channel;
|
||||
unsigned int creads = ts_dev->coordinate_readouts;
|
||||
|
||||
*z1 = *z2 = 0;
|
||||
if (fifocount % (creads * 2 + 2))
|
||||
fifocount -= fifocount % (creads * 2 + 2);
|
||||
/*
|
||||
* Delta filter is used to remove large variations in sampled
|
||||
* values from ADC. The filter tries to predict where the next
|
||||
|
|
@ -148,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
|
|||
* algorithm compares the difference with that of a present value,
|
||||
* if true the value is reported to the sub system.
|
||||
*/
|
||||
for (i = 0; i < fifocount - 1; i++) {
|
||||
for (i = 0; i < fifocount; i++) {
|
||||
read = titsc_readl(ts_dev, REG_FIFO0);
|
||||
channel = read & 0xf0000;
|
||||
channel = channel >> 0x10;
|
||||
if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
|
||||
read &= 0xfff;
|
||||
|
||||
channel = (read & 0xf0000) >> 16;
|
||||
read &= 0xfff;
|
||||
if (channel < creads) {
|
||||
diff = abs(read - prev_val_x);
|
||||
if (diff < prev_diff_x) {
|
||||
prev_diff_x = diff;
|
||||
*x = read;
|
||||
}
|
||||
prev_val_x = read;
|
||||
}
|
||||
|
||||
read = titsc_readl(ts_dev, REG_FIFO1);
|
||||
channel = read & 0xf0000;
|
||||
channel = channel >> 0x10;
|
||||
if ((channel >= ts_dev->steps_to_configure) &&
|
||||
(channel < (2 * ts_dev->steps_to_configure - 1))) {
|
||||
read &= 0xfff;
|
||||
} else if (channel < creads * 2) {
|
||||
diff = abs(read - prev_val_y);
|
||||
if (diff < prev_diff_y) {
|
||||
prev_diff_y = diff;
|
||||
*y = read;
|
||||
}
|
||||
prev_val_y = read;
|
||||
|
||||
} else if (channel < creads * 2 + 1) {
|
||||
*z1 = read;
|
||||
|
||||
} else if (channel < creads * 2 + 2) {
|
||||
*z2 = read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -186,23 +258,11 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||
unsigned int x = 0, y = 0;
|
||||
unsigned int z1, z2, z;
|
||||
unsigned int fsm;
|
||||
unsigned int fifo1count, fifo0count;
|
||||
int i;
|
||||
|
||||
status = titsc_readl(ts_dev, REG_IRQSTATUS);
|
||||
if (status & IRQENB_FIFO0THRES) {
|
||||
titsc_read_coordinates(ts_dev, &x, &y);
|
||||
|
||||
z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
|
||||
z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
|
||||
|
||||
fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
|
||||
for (i = 0; i < fifo1count; i++)
|
||||
titsc_readl(ts_dev, REG_FIFO1);
|
||||
|
||||
fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
|
||||
for (i = 0; i < fifo0count; i++)
|
||||
titsc_readl(ts_dev, REG_FIFO0);
|
||||
titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
|
||||
|
||||
if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
|
||||
/*
|
||||
|
|
@ -210,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||
* Resistance(touch) = x plate resistance *
|
||||
* x postion/4096 * ((z2 / z1) - 1)
|
||||
*/
|
||||
z = z2 - z1;
|
||||
z = z1 - z2;
|
||||
z *= x;
|
||||
z *= ts_dev->x_plate_resistance;
|
||||
z /= z1;
|
||||
z /= z2;
|
||||
z = (z + 2047) >> 12;
|
||||
|
||||
if (z <= MAX_12BIT) {
|
||||
|
|
@ -248,10 +308,53 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||
irqclr |= IRQENB_PENUP;
|
||||
}
|
||||
|
||||
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
|
||||
if (status & IRQENB_HW_PEN) {
|
||||
|
||||
titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
|
||||
return IRQ_HANDLED;
|
||||
titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
|
||||
titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
|
||||
}
|
||||
|
||||
if (irqclr) {
|
||||
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
|
||||
am335x_tsc_se_update(ts_dev->mfd_tscadc);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int titsc_parse_dt(struct platform_device *pdev,
|
||||
struct titsc *ts_dev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int err;
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
|
||||
if (err < 0)
|
||||
return err;
|
||||
switch (ts_dev->wires) {
|
||||
case 4:
|
||||
case 5:
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = of_property_read_u32(node, "ti,x-plate-resistance",
|
||||
&ts_dev->x_plate_resistance);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = of_property_read_u32(node, "ti,coordiante-readouts",
|
||||
&ts_dev->coordinate_readouts);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return of_property_read_u32_array(node, "ti,wire-config",
|
||||
ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -262,17 +365,9 @@ static int titsc_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct titsc *ts_dev;
|
||||
struct input_dev *input_dev;
|
||||
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
|
||||
struct mfd_tscadc_board *pdata;
|
||||
struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
|
||||
int err;
|
||||
|
||||
pdata = tscadc_dev->dev->platform_data;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Could not find platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allocate memory for device */
|
||||
ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
|
|
@ -286,9 +381,12 @@ static int titsc_probe(struct platform_device *pdev)
|
|||
ts_dev->mfd_tscadc = tscadc_dev;
|
||||
ts_dev->input = input_dev;
|
||||
ts_dev->irq = tscadc_dev->irq;
|
||||
ts_dev->wires = pdata->tsc_init->wires;
|
||||
ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
|
||||
ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
|
||||
|
||||
err = titsc_parse_dt(pdev, ts_dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Could not find valid DT data.\n");
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
err = request_irq(ts_dev->irq, titsc_irq,
|
||||
0, pdev->dev.driver->name, ts_dev);
|
||||
|
|
@ -298,8 +396,14 @@ static int titsc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
|
||||
err = titsc_config_wires(ts_dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "wrong i/p wire configuration\n");
|
||||
goto err_free_irq;
|
||||
}
|
||||
titsc_step_config(ts_dev);
|
||||
titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
|
||||
titsc_writel(ts_dev, REG_FIFO0THR,
|
||||
ts_dev->coordinate_readouts * 2 + 2 - 1);
|
||||
|
||||
input_dev->name = "ti-tsc";
|
||||
input_dev->dev.parent = &pdev->dev;
|
||||
|
|
@ -329,11 +433,16 @@ err_free_mem:
|
|||
|
||||
static int titsc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
|
||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
||||
struct titsc *ts_dev = platform_get_drvdata(pdev);
|
||||
u32 steps;
|
||||
|
||||
free_irq(ts_dev->irq, ts_dev);
|
||||
|
||||
/* total steps followed by the enable mask */
|
||||
steps = 2 * ts_dev->coordinate_readouts + 2;
|
||||
steps = (1 << steps) - 1;
|
||||
am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
|
||||
|
||||
input_unregister_device(ts_dev->input);
|
||||
|
||||
kfree(ts_dev);
|
||||
|
|
@ -343,10 +452,11 @@ static int titsc_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM
|
||||
static int titsc_suspend(struct device *dev)
|
||||
{
|
||||
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
|
||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
||||
struct titsc *ts_dev = dev_get_drvdata(dev);
|
||||
struct ti_tscadc_dev *tscadc_dev;
|
||||
unsigned int idle;
|
||||
|
||||
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
|
||||
if (device_may_wakeup(tscadc_dev->dev)) {
|
||||
idle = titsc_readl(ts_dev, REG_IRQENABLE);
|
||||
titsc_writel(ts_dev, REG_IRQENABLE,
|
||||
|
|
@ -358,9 +468,10 @@ static int titsc_suspend(struct device *dev)
|
|||
|
||||
static int titsc_resume(struct device *dev)
|
||||
{
|
||||
struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
|
||||
struct titsc *ts_dev = tscadc_dev->tsc;
|
||||
struct titsc *ts_dev = dev_get_drvdata(dev);
|
||||
struct ti_tscadc_dev *tscadc_dev;
|
||||
|
||||
tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
|
||||
if (device_may_wakeup(tscadc_dev->dev)) {
|
||||
titsc_writel(ts_dev, REG_IRQWAKEUP,
|
||||
0x00);
|
||||
|
|
@ -368,7 +479,7 @@ static int titsc_resume(struct device *dev)
|
|||
}
|
||||
titsc_step_config(ts_dev);
|
||||
titsc_writel(ts_dev, REG_FIFO0THR,
|
||||
ts_dev->steps_to_configure);
|
||||
ts_dev->coordinate_readouts * 2 + 2 - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -381,13 +492,20 @@ static const struct dev_pm_ops titsc_pm_ops = {
|
|||
#define TITSC_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id ti_tsc_dt_ids[] = {
|
||||
{ .compatible = "ti,am3359-tsc", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
|
||||
|
||||
static struct platform_driver ti_tsc_driver = {
|
||||
.probe = titsc_probe,
|
||||
.remove = titsc_remove,
|
||||
.driver = {
|
||||
.name = "tsc",
|
||||
.name = "TI-am335x-tsc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = TITSC_PM_OPS,
|
||||
.of_match_table = of_match_ptr(ti_tsc_dt_ids),
|
||||
},
|
||||
};
|
||||
module_platform_driver(ti_tsc_driver);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/tps6507x.h>
|
||||
#include <linux/input/tps6507x-ts.h>
|
||||
|
|
@ -38,20 +39,13 @@ struct ts_event {
|
|||
};
|
||||
|
||||
struct tps6507x_ts {
|
||||
struct input_dev *input_dev;
|
||||
struct device *dev;
|
||||
char phys[32];
|
||||
struct delayed_work work;
|
||||
unsigned polling; /* polling is active */
|
||||
struct ts_event tc;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct tps6507x_dev *mfd;
|
||||
u16 model;
|
||||
unsigned pendown;
|
||||
int irq;
|
||||
void (*clear_penirq)(void);
|
||||
unsigned long poll_period; /* ms */
|
||||
char phys[32];
|
||||
struct ts_event tc;
|
||||
u16 min_pressure;
|
||||
int vref; /* non-zero to leave vref on */
|
||||
bool pendown;
|
||||
};
|
||||
|
||||
static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
|
||||
|
|
@ -161,18 +155,15 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void tps6507x_ts_handler(struct work_struct *work)
|
||||
static void tps6507x_ts_poll(struct input_polled_dev *poll_dev)
|
||||
{
|
||||
struct tps6507x_ts *tsc = container_of(work,
|
||||
struct tps6507x_ts, work.work);
|
||||
struct input_dev *input_dev = tsc->input_dev;
|
||||
int pendown;
|
||||
int schd;
|
||||
int poll = 0;
|
||||
struct tps6507x_ts *tsc = poll_dev->private;
|
||||
struct input_dev *input_dev = poll_dev->input;
|
||||
bool pendown;
|
||||
s32 ret;
|
||||
|
||||
ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
|
||||
&tsc->tc.pressure);
|
||||
ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
|
||||
&tsc->tc.pressure);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
@ -183,7 +174,7 @@ static void tps6507x_ts_handler(struct work_struct *work)
|
|||
input_report_key(input_dev, BTN_TOUCH, 0);
|
||||
input_report_abs(input_dev, ABS_PRESSURE, 0);
|
||||
input_sync(input_dev);
|
||||
tsc->pendown = 0;
|
||||
tsc->pendown = false;
|
||||
}
|
||||
|
||||
if (pendown) {
|
||||
|
|
@ -208,76 +199,69 @@ static void tps6507x_ts_handler(struct work_struct *work)
|
|||
input_report_abs(input_dev, ABS_Y, tsc->tc.y);
|
||||
input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure);
|
||||
input_sync(input_dev);
|
||||
tsc->pendown = 1;
|
||||
poll = 1;
|
||||
tsc->pendown = true;
|
||||
}
|
||||
|
||||
done:
|
||||
/* always poll if not using interrupts */
|
||||
poll = 1;
|
||||
|
||||
if (poll) {
|
||||
schd = schedule_delayed_work(&tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
if (schd)
|
||||
tsc->polling = 1;
|
||||
else {
|
||||
tsc->polling = 0;
|
||||
dev_err(tsc->dev, "re-schedule failed");
|
||||
}
|
||||
} else
|
||||
tsc->polling = 0;
|
||||
|
||||
ret = tps6507x_adc_standby(tsc);
|
||||
tps6507x_adc_standby(tsc);
|
||||
}
|
||||
|
||||
static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
{
|
||||
int error;
|
||||
struct tps6507x_ts *tsc;
|
||||
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct touchscreen_init_data *init_data;
|
||||
const struct tps6507x_board *tps_board;
|
||||
const struct touchscreen_init_data *init_data;
|
||||
struct tps6507x_ts *tsc;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input_dev;
|
||||
struct tps6507x_board *tps_board;
|
||||
int schd;
|
||||
int error;
|
||||
|
||||
/**
|
||||
/*
|
||||
* tps_board points to pmic related constants
|
||||
* coming from the board-evm file.
|
||||
*/
|
||||
|
||||
tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data;
|
||||
|
||||
tps_board = dev_get_platdata(tps6507x_dev->dev);
|
||||
if (!tps_board) {
|
||||
dev_err(tps6507x_dev->dev,
|
||||
"Could not find tps6507x platform data\n");
|
||||
return -EIO;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* init_data points to array of regulator_init structures
|
||||
* coming from the board-evm file.
|
||||
*/
|
||||
|
||||
init_data = tps_board->tps6507x_ts_init_data;
|
||||
|
||||
tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL);
|
||||
if (!tsc) {
|
||||
dev_err(tps6507x_dev->dev, "failed to allocate driver data\n");
|
||||
error = -ENOMEM;
|
||||
goto err0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps6507x_dev->ts = tsc;
|
||||
tsc->mfd = tps6507x_dev;
|
||||
tsc->dev = tps6507x_dev->dev;
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(tsc->dev, "Failed to allocate input device.\n");
|
||||
tsc->min_pressure = init_data ?
|
||||
init_data->min_pressure : TPS_DEFAULT_MIN_PRESSURE;
|
||||
|
||||
snprintf(tsc->phys, sizeof(tsc->phys),
|
||||
"%s/input0", dev_name(tsc->dev));
|
||||
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!poll_dev) {
|
||||
dev_err(tsc->dev, "Failed to allocate polled input device.\n");
|
||||
error = -ENOMEM;
|
||||
goto err1;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
tsc->poll_dev = poll_dev;
|
||||
|
||||
poll_dev->private = tsc;
|
||||
poll_dev->poll = tps6507x_ts_poll;
|
||||
poll_dev->poll_interval = init_data ?
|
||||
init_data->poll_period : TSC_DEFAULT_POLL_PERIOD;
|
||||
|
||||
input_dev = poll_dev->input;
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
|
||||
|
|
@ -286,76 +270,42 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
|||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
|
||||
|
||||
input_dev->name = "TPS6507x Touchscreen";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = tsc->dev;
|
||||
|
||||
snprintf(tsc->phys, sizeof(tsc->phys),
|
||||
"%s/input0", dev_name(tsc->dev));
|
||||
input_dev->phys = tsc->phys;
|
||||
|
||||
dev_dbg(tsc->dev, "device: %s\n", input_dev->phys);
|
||||
|
||||
input_set_drvdata(input_dev, tsc);
|
||||
|
||||
tsc->input_dev = input_dev;
|
||||
|
||||
INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
|
||||
|
||||
input_dev->dev.parent = tsc->dev;
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
if (init_data) {
|
||||
tsc->poll_period = init_data->poll_period;
|
||||
tsc->vref = init_data->vref;
|
||||
tsc->min_pressure = init_data->min_pressure;
|
||||
input_dev->id.vendor = init_data->vendor;
|
||||
input_dev->id.product = init_data->product;
|
||||
input_dev->id.version = init_data->version;
|
||||
} else {
|
||||
tsc->poll_period = TSC_DEFAULT_POLL_PERIOD;
|
||||
tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE;
|
||||
}
|
||||
|
||||
error = tps6507x_adc_standby(tsc);
|
||||
if (error)
|
||||
goto err2;
|
||||
goto err_free_polled_dev;
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
error = input_register_polled_device(poll_dev);
|
||||
if (error)
|
||||
goto err2;
|
||||
goto err_free_polled_dev;
|
||||
|
||||
schd = schedule_delayed_work(&tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
|
||||
if (schd)
|
||||
tsc->polling = 1;
|
||||
else {
|
||||
tsc->polling = 0;
|
||||
dev_err(tsc->dev, "schedule failed");
|
||||
goto err2;
|
||||
}
|
||||
platform_set_drvdata(pdev, tps6507x_dev);
|
||||
platform_set_drvdata(pdev, tsc);
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
cancel_delayed_work_sync(&tsc->work);
|
||||
input_free_device(input_dev);
|
||||
err1:
|
||||
err_free_polled_dev:
|
||||
input_free_polled_device(poll_dev);
|
||||
err_free_mem:
|
||||
kfree(tsc);
|
||||
tps6507x_dev->ts = NULL;
|
||||
err0:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int tps6507x_ts_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
|
||||
struct tps6507x_ts *tsc = tps6507x_dev->ts;
|
||||
struct input_dev *input_dev = tsc->input_dev;
|
||||
struct tps6507x_ts *tsc = platform_get_drvdata(pdev);
|
||||
struct input_polled_dev *poll_dev = tsc->poll_dev;
|
||||
|
||||
cancel_delayed_work_sync(&tsc->work);
|
||||
input_unregister_polled_device(poll_dev);
|
||||
input_free_polled_device(poll_dev);
|
||||
|
||||
input_unregister_device(input_dev);
|
||||
|
||||
tps6507x_dev->ts = NULL;
|
||||
kfree(tsc);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue