Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input layer updates from Dmitry Torokhov: - evdev interface has been adjusted to extend the life of timestamps on 32 bit systems to the year of 2108 - Synaptics RMI4 driver's PS/2 guest handling ha beed updated to improve chances of detecting trackpoints on the pass-through port - mms114 touchcsreen controller driver has been updated to support generic device properties and work with mms152 cntrollers - Goodix driver now supports generic touchscreen properties - couple of drivers for AVR32 architecture are gone as the architecture support has been removed from the kernel - gpio-tilt driver has been removed as there are no mainline users and the driver itself is using legacy APIs and relies on platform data - MODULE_LINECSE/MODULE_VERSION cleanups * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (45 commits) Input: goodix - use generic touchscreen_properties Input: mms114 - fix typo in definition Input: mms114 - use BIT() macro instead of explicit shifting Input: mms114 - replace mdelay with msleep Input: mms114 - add support for mms152 Input: mms114 - drop platform data and use generic APIs Input: mms114 - mark as direct input device Input: mms114 - do not clobber interrupt trigger Input: edt-ft5x06 - fix error handling for factory mode on non-M06 Input: stmfts - set IRQ_NOAUTOEN to the irq flag Input: auo-pixcir-ts - delete an unnecessary return statement Input: auo-pixcir-ts - remove custom log for a failed memory allocation Input: da9052_tsi - remove unused mutex Input: docs - use PROPERTY_ENTRY_U32() directly Input: synaptics-rmi4 - log when we create a guest serio port Input: synaptics-rmi4 - unmask F03 interrupts when port is opened Input: synaptics-rmi4 - do not delete interrupt memory too early Input: ad7877 - use managed resource allocations Input: stmfts,s6sy671 - add SPDX identifier Input: remove atmel-wm97xx touchscreen driver ...
This commit is contained in:
@@ -795,21 +795,6 @@ config TOUCHSCREEN_WM9713
|
||||
Say Y here to enable support for the Wolfson Microelectronics
|
||||
WM9713 touchscreen controller.
|
||||
|
||||
config TOUCHSCREEN_WM97XX_ATMEL
|
||||
tristate "WM97xx Atmel accelerated touch"
|
||||
depends on TOUCHSCREEN_WM97XX && AVR32
|
||||
help
|
||||
Say Y here for support for streaming mode with WM97xx touchscreens
|
||||
on Atmel AT91 or AVR32 systems with an AC97C module.
|
||||
|
||||
Be aware that this will use channel B in the controller for
|
||||
streaming data, this must not conflict with other AC97C drivers.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called atmel-wm97xx.
|
||||
|
||||
config TOUCHSCREEN_WM97XX_MAINSTONE
|
||||
tristate "WM97xx Mainstone/Palm accelerated touch"
|
||||
depends on TOUCHSCREEN_WM97XX && ARCH_PXA
|
||||
|
@@ -97,7 +97,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
|
||||
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
|
||||
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
|
||||
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
|
||||
|
@@ -417,8 +417,10 @@ out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void ad7877_disable(struct ad7877 *ts)
|
||||
static void ad7877_disable(void *data)
|
||||
{
|
||||
struct ad7877 *ts = data;
|
||||
|
||||
mutex_lock(&ts->mutex);
|
||||
|
||||
if (!ts->disabled) {
|
||||
@@ -707,12 +709,17 @@ static int ad7877_probe(struct spi_device *spi)
|
||||
return err;
|
||||
}
|
||||
|
||||
ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ts || !input_dev) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
ts = devm_kzalloc(&spi->dev, sizeof(struct ad7877), GFP_KERNEL);
|
||||
if (!ts)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev = devm_input_allocate_device(&spi->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
err = devm_add_action_or_reset(&spi->dev, ad7877_disable, ts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
spi_set_drvdata(spi, ts);
|
||||
ts->spi = spi;
|
||||
@@ -761,11 +768,10 @@ static int ad7877_probe(struct spi_device *spi)
|
||||
|
||||
verify = ad7877_read(spi, AD7877_REG_SEQ1);
|
||||
|
||||
if (verify != AD7877_MM_SEQUENCE){
|
||||
if (verify != AD7877_MM_SEQUENCE) {
|
||||
dev_err(&spi->dev, "%s: Failed to probe %s\n",
|
||||
dev_name(&spi->dev), input_dev->name);
|
||||
err = -ENODEV;
|
||||
goto err_free_mem;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (gpio3)
|
||||
@@ -775,47 +781,21 @@ static int ad7877_probe(struct spi_device *spi)
|
||||
|
||||
/* Request AD7877 /DAV GPIO interrupt */
|
||||
|
||||
err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
spi->dev.driver->name, ts);
|
||||
err = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, ad7877_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
spi->dev.driver->name, ts);
|
||||
if (err) {
|
||||
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
|
||||
goto err_free_mem;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = sysfs_create_group(&spi->dev.kobj, &ad7877_attr_group);
|
||||
err = devm_device_add_group(&spi->dev, &ad7877_attr_group);
|
||||
if (err)
|
||||
goto err_free_irq;
|
||||
return err;
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err)
|
||||
goto err_remove_attr_group;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_attr_group:
|
||||
sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
|
||||
err_free_irq:
|
||||
free_irq(spi->irq, ts);
|
||||
err_free_mem:
|
||||
input_free_device(input_dev);
|
||||
kfree(ts);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ad7877_remove(struct spi_device *spi)
|
||||
{
|
||||
struct ad7877 *ts = spi_get_drvdata(spi);
|
||||
|
||||
sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
|
||||
|
||||
ad7877_disable(ts);
|
||||
free_irq(ts->spi->irq, ts);
|
||||
|
||||
input_unregister_device(ts->input);
|
||||
kfree(ts);
|
||||
|
||||
dev_dbg(&spi->dev, "unregistered touchscreen\n");
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -846,7 +826,6 @@ static struct spi_driver ad7877_driver = {
|
||||
.pm = &ad7877_pm,
|
||||
},
|
||||
.probe = ad7877_probe,
|
||||
.remove = ad7877_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(ad7877_driver);
|
||||
|
@@ -1,436 +0,0 @@
|
||||
/*
|
||||
* Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97
|
||||
* codecs.
|
||||
*
|
||||
* Copyright (C) 2008 - 2009 Atmel Corporation
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wm97xx.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define AC97C_ICA 0x10
|
||||
#define AC97C_CBRHR 0x30
|
||||
#define AC97C_CBSR 0x38
|
||||
#define AC97C_CBMR 0x3c
|
||||
#define AC97C_IER 0x54
|
||||
#define AC97C_IDR 0x58
|
||||
|
||||
#define AC97C_RXRDY (1 << 4)
|
||||
#define AC97C_OVRUN (1 << 5)
|
||||
|
||||
#define AC97C_CMR_SIZE_20 (0 << 16)
|
||||
#define AC97C_CMR_SIZE_18 (1 << 16)
|
||||
#define AC97C_CMR_SIZE_16 (2 << 16)
|
||||
#define AC97C_CMR_SIZE_10 (3 << 16)
|
||||
#define AC97C_CMR_CEM_LITTLE (1 << 18)
|
||||
#define AC97C_CMR_CEM_BIG (0 << 18)
|
||||
#define AC97C_CMR_CENA (1 << 21)
|
||||
|
||||
#define AC97C_INT_CBEVT (1 << 4)
|
||||
|
||||
#define AC97C_SR_CAEVT (1 << 3)
|
||||
|
||||
#define AC97C_CH_MASK(slot) \
|
||||
(0x7 << (3 * (slot - 3)))
|
||||
#define AC97C_CH_ASSIGN(slot, channel) \
|
||||
(AC97C_CHANNEL_##channel << (3 * (slot - 3)))
|
||||
#define AC97C_CHANNEL_NONE 0x0
|
||||
#define AC97C_CHANNEL_B 0x2
|
||||
|
||||
#define ac97c_writel(chip, reg, val) \
|
||||
__raw_writel((val), (chip)->regs + AC97C_##reg)
|
||||
#define ac97c_readl(chip, reg) \
|
||||
__raw_readl((chip)->regs + AC97C_##reg)
|
||||
|
||||
#ifdef CONFIG_CPU_AT32AP700X
|
||||
#define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800)
|
||||
#define ATMEL_WM97XX_AC97C_IRQ (29)
|
||||
#define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */
|
||||
#else
|
||||
#error Unknown CPU, this driver only supports AT32AP700X CPUs.
|
||||
#endif
|
||||
|
||||
struct continuous {
|
||||
u16 id; /* codec id */
|
||||
u8 code; /* continuous code */
|
||||
u8 reads; /* number of coord reads per read cycle */
|
||||
u32 speed; /* number of coords per second */
|
||||
};
|
||||
|
||||
#define WM_READS(sp) ((sp / HZ) + 1)
|
||||
|
||||
static const struct continuous cinfo[] = {
|
||||
{WM9705_ID2, 0, WM_READS(94), 94},
|
||||
{WM9705_ID2, 1, WM_READS(188), 188},
|
||||
{WM9705_ID2, 2, WM_READS(375), 375},
|
||||
{WM9705_ID2, 3, WM_READS(750), 750},
|
||||
{WM9712_ID2, 0, WM_READS(94), 94},
|
||||
{WM9712_ID2, 1, WM_READS(188), 188},
|
||||
{WM9712_ID2, 2, WM_READS(375), 375},
|
||||
{WM9712_ID2, 3, WM_READS(750), 750},
|
||||
{WM9713_ID2, 0, WM_READS(94), 94},
|
||||
{WM9713_ID2, 1, WM_READS(120), 120},
|
||||
{WM9713_ID2, 2, WM_READS(154), 154},
|
||||
{WM9713_ID2, 3, WM_READS(188), 188},
|
||||
};
|
||||
|
||||
/* Continuous speed index. */
|
||||
static int sp_idx;
|
||||
|
||||
/*
|
||||
* Pen sampling frequency (Hz) in continuous mode.
|
||||
*/
|
||||
static int cont_rate = 188;
|
||||
module_param(cont_rate, int, 0);
|
||||
MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
|
||||
|
||||
/*
|
||||
* Pen down detection.
|
||||
*
|
||||
* This driver can either poll or use an interrupt to indicate a pen down
|
||||
* event. If the irq request fails then it will fall back to polling mode.
|
||||
*/
|
||||
static int pen_int = 1;
|
||||
module_param(pen_int, int, 0);
|
||||
MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
|
||||
|
||||
/*
|
||||
* Pressure readback.
|
||||
*
|
||||
* Set to 1 to read back pen down pressure.
|
||||
*/
|
||||
static int pressure;
|
||||
module_param(pressure, int, 0);
|
||||
MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
|
||||
|
||||
/*
|
||||
* AC97 touch data slot.
|
||||
*
|
||||
* Touch screen readback data ac97 slot.
|
||||
*/
|
||||
static int ac97_touch_slot = 5;
|
||||
module_param(ac97_touch_slot, int, 0);
|
||||
MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
|
||||
|
||||
/*
|
||||
* GPIO line number.
|
||||
*
|
||||
* Set to GPIO number where the signal from the WM97xx device is hooked up.
|
||||
*/
|
||||
static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT;
|
||||
module_param(atmel_gpio_line, int, 0);
|
||||
MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx");
|
||||
|
||||
struct atmel_wm97xx {
|
||||
struct wm97xx *wm;
|
||||
struct timer_list pen_timer;
|
||||
void __iomem *regs;
|
||||
unsigned long ac97c_irq;
|
||||
unsigned long gpio_pen;
|
||||
unsigned long gpio_irq;
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
};
|
||||
|
||||
static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct atmel_wm97xx *atmel_wm97xx = dev_id;
|
||||
struct wm97xx *wm = atmel_wm97xx->wm;
|
||||
int status = ac97c_readl(atmel_wm97xx, CBSR);
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
|
||||
if (status & AC97C_OVRUN) {
|
||||
dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n");
|
||||
ac97c_readl(atmel_wm97xx, CBRHR);
|
||||
retval = IRQ_HANDLED;
|
||||
} else if (status & AC97C_RXRDY) {
|
||||
u16 data;
|
||||
u16 value;
|
||||
u16 source;
|
||||
u16 pen_down;
|
||||
|
||||
data = ac97c_readl(atmel_wm97xx, CBRHR);
|
||||
value = data & 0x0fff;
|
||||
source = data & WM97XX_ADCSEL_MASK;
|
||||
pen_down = (data & WM97XX_PEN_DOWN) >> 8;
|
||||
|
||||
if (source == WM97XX_ADCSEL_X)
|
||||
atmel_wm97xx->x = value;
|
||||
if (source == WM97XX_ADCSEL_Y)
|
||||
atmel_wm97xx->y = value;
|
||||
|
||||
if (!pressure && source == WM97XX_ADCSEL_Y) {
|
||||
input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
|
||||
input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
|
||||
input_report_key(wm->input_dev, BTN_TOUCH, pen_down);
|
||||
input_sync(wm->input_dev);
|
||||
} else if (pressure && source == WM97XX_ADCSEL_PRES) {
|
||||
input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
|
||||
input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
|
||||
input_report_abs(wm->input_dev, ABS_PRESSURE, value);
|
||||
input_report_key(wm->input_dev, BTN_TOUCH, value);
|
||||
input_sync(wm->input_dev);
|
||||
}
|
||||
|
||||
retval = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
|
||||
{
|
||||
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
|
||||
struct input_dev *input_dev = wm->input_dev;
|
||||
int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen);
|
||||
|
||||
if (pen_down != 0) {
|
||||
mod_timer(&atmel_wm97xx->pen_timer,
|
||||
jiffies + msecs_to_jiffies(1));
|
||||
} else {
|
||||
if (pressure)
|
||||
input_report_abs(input_dev, ABS_PRESSURE, 0);
|
||||
input_report_key(input_dev, BTN_TOUCH, 0);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void atmel_wm97xx_pen_timer(struct timer_list *t)
|
||||
{
|
||||
struct atmel_wm97xx *atmel_wm97xx = from_timer(atmel_wm97xx, t,
|
||||
pen_timer);
|
||||
|
||||
atmel_wm97xx_acc_pen_up(atmel_wm97xx->wm);
|
||||
}
|
||||
|
||||
static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
|
||||
{
|
||||
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
|
||||
int idx = 0;
|
||||
|
||||
if (wm->ac97 == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
|
||||
if (wm->id != cinfo[idx].id)
|
||||
continue;
|
||||
|
||||
sp_idx = idx;
|
||||
|
||||
if (cont_rate <= cinfo[idx].speed)
|
||||
break;
|
||||
}
|
||||
|
||||
wm->acc_rate = cinfo[sp_idx].code;
|
||||
wm->acc_slot = ac97_touch_slot;
|
||||
dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, "
|
||||
"%d samples/sec\n", cinfo[sp_idx].speed);
|
||||
|
||||
if (pen_int) {
|
||||
unsigned long reg;
|
||||
|
||||
wm->pen_irq = atmel_wm97xx->gpio_irq;
|
||||
|
||||
switch (wm->id) {
|
||||
case WM9712_ID2: /* Fall through. */
|
||||
case WM9713_ID2:
|
||||
/*
|
||||
* Use GPIO 13 (PEN_DOWN) to assert GPIO line 3
|
||||
* (PENDOWN).
|
||||
*/
|
||||
wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
|
||||
WM97XX_GPIO_POL_HIGH,
|
||||
WM97XX_GPIO_STICKY,
|
||||
WM97XX_GPIO_WAKE);
|
||||
wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT,
|
||||
WM97XX_GPIO_POL_HIGH,
|
||||
WM97XX_GPIO_NOTSTICKY,
|
||||
WM97XX_GPIO_NOWAKE);
|
||||
case WM9705_ID2: /* Fall through. */
|
||||
/*
|
||||
* Enable touch data slot in AC97 controller channel B.
|
||||
*/
|
||||
reg = ac97c_readl(atmel_wm97xx, ICA);
|
||||
reg &= ~AC97C_CH_MASK(wm->acc_slot);
|
||||
reg |= AC97C_CH_ASSIGN(wm->acc_slot, B);
|
||||
ac97c_writel(atmel_wm97xx, ICA, reg);
|
||||
|
||||
/*
|
||||
* Enable channel and interrupt for RXRDY and OVERRUN.
|
||||
*/
|
||||
ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA
|
||||
| AC97C_CMR_CEM_BIG
|
||||
| AC97C_CMR_SIZE_16
|
||||
| AC97C_OVRUN
|
||||
| AC97C_RXRDY);
|
||||
/* Dummy read to empty RXRHR. */
|
||||
ac97c_readl(atmel_wm97xx, CBRHR);
|
||||
/*
|
||||
* Enable interrupt for channel B in the AC97
|
||||
* controller.
|
||||
*/
|
||||
ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
|
||||
break;
|
||||
default:
|
||||
dev_err(&wm->touch_dev->dev, "pen down irq not "
|
||||
"supported on this device\n");
|
||||
pen_int = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm)
|
||||
{
|
||||
if (pen_int) {
|
||||
struct atmel_wm97xx *atmel_wm97xx =
|
||||
platform_get_drvdata(wm->touch_dev);
|
||||
unsigned long ica;
|
||||
|
||||
switch (wm->id & 0xffff) {
|
||||
case WM9705_ID2: /* Fall through. */
|
||||
case WM9712_ID2: /* Fall through. */
|
||||
case WM9713_ID2:
|
||||
/* Disable slot and turn off channel B interrupts. */
|
||||
ica = ac97c_readl(atmel_wm97xx, ICA);
|
||||
ica &= ~AC97C_CH_MASK(wm->acc_slot);
|
||||
ac97c_writel(atmel_wm97xx, ICA, ica);
|
||||
ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
|
||||
ac97c_writel(atmel_wm97xx, CBMR, 0);
|
||||
wm->pen_irq = 0;
|
||||
break;
|
||||
default:
|
||||
dev_err(&wm->touch_dev->dev, "unknown codec\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable)
|
||||
{
|
||||
/* Intentionally left empty. */
|
||||
}
|
||||
|
||||
static struct wm97xx_mach_ops atmel_mach_ops = {
|
||||
.acc_enabled = 1,
|
||||
.acc_pen_up = atmel_wm97xx_acc_pen_up,
|
||||
.acc_startup = atmel_wm97xx_acc_startup,
|
||||
.acc_shutdown = atmel_wm97xx_acc_shutdown,
|
||||
.irq_enable = atmel_wm97xx_irq_enable,
|
||||
.irq_gpio = WM97XX_GPIO_3,
|
||||
};
|
||||
|
||||
static int __init atmel_wm97xx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm97xx *wm = platform_get_drvdata(pdev);
|
||||
struct atmel_wm97xx *atmel_wm97xx;
|
||||
int ret;
|
||||
|
||||
atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL);
|
||||
if (!atmel_wm97xx)
|
||||
return -ENOMEM;
|
||||
|
||||
atmel_wm97xx->wm = wm;
|
||||
atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM;
|
||||
atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ;
|
||||
atmel_wm97xx->gpio_pen = atmel_gpio_line;
|
||||
atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
|
||||
|
||||
timer_setup(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 0);
|
||||
|
||||
ret = request_irq(atmel_wm97xx->ac97c_irq,
|
||||
atmel_wm97xx_channel_b_interrupt,
|
||||
IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx);
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "could not request ac97c irq\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, atmel_wm97xx);
|
||||
|
||||
ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops);
|
||||
if (ret)
|
||||
goto err_irq;
|
||||
|
||||
return ret;
|
||||
|
||||
err_irq:
|
||||
free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
|
||||
err:
|
||||
kfree(atmel_wm97xx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
|
||||
struct wm97xx *wm = atmel_wm97xx->wm;
|
||||
|
||||
ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
|
||||
free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
|
||||
del_timer_sync(&atmel_wm97xx->pen_timer);
|
||||
wm97xx_unregister_mach_ops(wm);
|
||||
kfree(atmel_wm97xx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int atmel_wm97xx_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
|
||||
|
||||
ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
|
||||
disable_irq(atmel_wm97xx->gpio_irq);
|
||||
del_timer_sync(&atmel_wm97xx->pen_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atmel_wm97xx_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
|
||||
struct wm97xx *wm = atmel_wm97xx->wm;
|
||||
|
||||
if (wm->input_dev->users) {
|
||||
enable_irq(atmel_wm97xx->gpio_irq);
|
||||
ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops,
|
||||
atmel_wm97xx_suspend, atmel_wm97xx_resume);
|
||||
|
||||
static struct platform_driver atmel_wm97xx_driver = {
|
||||
.remove = __exit_p(atmel_wm97xx_remove),
|
||||
.driver = {
|
||||
.name = "wm97xx-touch",
|
||||
.pm = &atmel_wm97xx_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(atmel_wm97xx_driver, atmel_wm97xx_probe);
|
||||
|
||||
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
|
||||
MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
|
||||
MODULE_LICENSE("GPL");
|
@@ -408,8 +408,6 @@ static void auo_pixcir_input_close(struct input_dev *dev)
|
||||
struct auo_pixcir_ts *ts = input_get_drvdata(dev);
|
||||
|
||||
auo_pixcir_stop(ts);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int __maybe_unused auo_pixcir_suspend(struct device *dev)
|
||||
@@ -487,10 +485,8 @@ static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(dev, "failed to allocate platform data\n");
|
||||
if (!pdata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
pdata->gpio_int = of_get_gpio(np, 0);
|
||||
if (!gpio_is_valid(pdata->gpio_int)) {
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DRIVER_NAME "colibri-vf50-ts"
|
||||
#define DRV_VERSION "1.0"
|
||||
|
||||
#define VF_ADC_MAX ((1 << 12) - 1)
|
||||
|
||||
@@ -382,4 +381,3 @@ module_platform_driver(vf50_touch_driver);
|
||||
MODULE_AUTHOR("Sanchayan Maity");
|
||||
MODULE_DESCRIPTION("Colibri VF50 Touchscreen driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
@@ -26,7 +26,6 @@ struct da9052_tsi {
|
||||
struct da9052 *da9052;
|
||||
struct input_dev *dev;
|
||||
struct delayed_work ts_pen_work;
|
||||
struct mutex mutex;
|
||||
bool stopped;
|
||||
bool adc_on;
|
||||
};
|
||||
|
@@ -511,6 +511,12 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
|
||||
int ret;
|
||||
int error;
|
||||
|
||||
if (tsdata->version != EDT_M06) {
|
||||
dev_err(&client->dev,
|
||||
"No factory mode support for non-M06 devices\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (!tsdata->raw_buffer) {
|
||||
@@ -524,9 +530,6 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
|
||||
}
|
||||
|
||||
/* mode register is 0x3c when in the work mode */
|
||||
if (tsdata->version != EDT_M06)
|
||||
goto m09_out;
|
||||
|
||||
error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
@@ -559,11 +562,6 @@ err_out:
|
||||
enable_irq(client->irq);
|
||||
|
||||
return error;
|
||||
|
||||
m09_out:
|
||||
dev_err(&client->dev, "No factory mode support for M09/M12/GENERIC_FT\n");
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
|
||||
|
@@ -45,7 +45,6 @@
|
||||
|
||||
/* Device, Driver information */
|
||||
#define DEVICE_NAME "elants_i2c"
|
||||
#define DRV_VERSION "1.0.9"
|
||||
|
||||
/* Convert from rows or columns into resolution */
|
||||
#define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m))
|
||||
@@ -1406,5 +1405,4 @@ module_i2c_driver(elants_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>");
|
||||
MODULE_DESCRIPTION("Elan I2c Touchscreen driver");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -43,11 +44,7 @@ struct goodix_ts_data {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
const struct goodix_chip_data *chip;
|
||||
int abs_x_max;
|
||||
int abs_y_max;
|
||||
bool swapped_x_y;
|
||||
bool inverted_x;
|
||||
bool inverted_y;
|
||||
struct touchscreen_properties prop;
|
||||
unsigned int max_touch_num;
|
||||
unsigned int int_trigger_type;
|
||||
struct gpio_desc *gpiod_int;
|
||||
@@ -160,7 +157,7 @@ static int goodix_i2c_read(struct i2c_client *client,
|
||||
u16 reg, u8 *buf, int len)
|
||||
{
|
||||
struct i2c_msg msgs[2];
|
||||
u16 wbuf = cpu_to_be16(reg);
|
||||
__be16 wbuf = cpu_to_be16(reg);
|
||||
int ret;
|
||||
|
||||
msgs[0].flags = 0;
|
||||
@@ -295,18 +292,10 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
|
||||
int input_y = get_unaligned_le16(&coor_data[3]);
|
||||
int input_w = get_unaligned_le16(&coor_data[5]);
|
||||
|
||||
/* Inversions have to happen before axis swapping */
|
||||
if (ts->inverted_x)
|
||||
input_x = ts->abs_x_max - input_x;
|
||||
if (ts->inverted_y)
|
||||
input_y = ts->abs_y_max - input_y;
|
||||
if (ts->swapped_x_y)
|
||||
swap(input_x, input_y);
|
||||
|
||||
input_mt_slot(ts->input_dev, id);
|
||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
|
||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
|
||||
touchscreen_report_pos(ts->input_dev, &ts->prop,
|
||||
input_x, input_y, true);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
|
||||
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
|
||||
}
|
||||
@@ -579,44 +568,27 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
|
||||
static void goodix_read_config(struct goodix_ts_data *ts)
|
||||
{
|
||||
u8 config[GOODIX_CONFIG_MAX_LENGTH];
|
||||
int x_max, y_max;
|
||||
int error;
|
||||
|
||||
error = goodix_i2c_read(ts->client, ts->chip->config_addr,
|
||||
config, ts->chip->config_len);
|
||||
if (error) {
|
||||
dev_warn(&ts->client->dev,
|
||||
"Error reading config (%d), using defaults\n",
|
||||
dev_warn(&ts->client->dev, "Error reading config: %d\n",
|
||||
error);
|
||||
ts->abs_x_max = GOODIX_MAX_WIDTH;
|
||||
ts->abs_y_max = GOODIX_MAX_HEIGHT;
|
||||
if (ts->swapped_x_y)
|
||||
swap(ts->abs_x_max, ts->abs_y_max);
|
||||
ts->int_trigger_type = GOODIX_INT_TRIGGER;
|
||||
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
||||
return;
|
||||
}
|
||||
|
||||
ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
|
||||
ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
|
||||
if (ts->swapped_x_y)
|
||||
swap(ts->abs_x_max, ts->abs_y_max);
|
||||
ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
|
||||
ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
|
||||
if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
|
||||
dev_err(&ts->client->dev,
|
||||
"Invalid config, using defaults\n");
|
||||
ts->abs_x_max = GOODIX_MAX_WIDTH;
|
||||
ts->abs_y_max = GOODIX_MAX_HEIGHT;
|
||||
if (ts->swapped_x_y)
|
||||
swap(ts->abs_x_max, ts->abs_y_max);
|
||||
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
||||
}
|
||||
|
||||
if (dmi_check_system(rotated_screen)) {
|
||||
ts->inverted_x = true;
|
||||
ts->inverted_y = true;
|
||||
dev_dbg(&ts->client->dev,
|
||||
"Applying '180 degrees rotated screen' quirk\n");
|
||||
x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
|
||||
y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
|
||||
if (x_max && y_max) {
|
||||
input_abs_set_max(ts->input_dev, ABS_MT_POSITION_X, x_max - 1);
|
||||
input_abs_set_max(ts->input_dev, ABS_MT_POSITION_Y, y_max - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,53 +647,6 @@ static int goodix_i2c_test(struct i2c_client *client)
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* goodix_request_input_dev - Allocate, populate and register the input device
|
||||
*
|
||||
* @ts: our goodix_ts_data pointer
|
||||
*
|
||||
* Must be called during probe
|
||||
*/
|
||||
static int goodix_request_input_dev(struct goodix_ts_data *ts)
|
||||
{
|
||||
int error;
|
||||
|
||||
ts->input_dev = devm_input_allocate_device(&ts->client->dev);
|
||||
if (!ts->input_dev) {
|
||||
dev_err(&ts->client->dev, "Failed to allocate input device.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
|
||||
0, ts->abs_x_max, 0, 0);
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
|
||||
0, ts->abs_y_max, 0, 0);
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
|
||||
|
||||
input_mt_init_slots(ts->input_dev, ts->max_touch_num,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
|
||||
|
||||
ts->input_dev->name = "Goodix Capacitive TouchScreen";
|
||||
ts->input_dev->phys = "input/ts";
|
||||
ts->input_dev->id.bustype = BUS_I2C;
|
||||
ts->input_dev->id.vendor = 0x0416;
|
||||
ts->input_dev->id.product = ts->id;
|
||||
ts->input_dev->id.version = ts->version;
|
||||
|
||||
/* Capacitive Windows/Home button on some devices */
|
||||
input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
|
||||
|
||||
error = input_register_device(ts->input_dev);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
"Failed to register input device: %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* goodix_configure_dev - Finish device initialization
|
||||
*
|
||||
@@ -736,18 +661,68 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
|
||||
{
|
||||
int error;
|
||||
|
||||
ts->swapped_x_y = device_property_read_bool(&ts->client->dev,
|
||||
"touchscreen-swapped-x-y");
|
||||
ts->inverted_x = device_property_read_bool(&ts->client->dev,
|
||||
"touchscreen-inverted-x");
|
||||
ts->inverted_y = device_property_read_bool(&ts->client->dev,
|
||||
"touchscreen-inverted-y");
|
||||
ts->int_trigger_type = GOODIX_INT_TRIGGER;
|
||||
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
||||
|
||||
ts->input_dev = devm_input_allocate_device(&ts->client->dev);
|
||||
if (!ts->input_dev) {
|
||||
dev_err(&ts->client->dev, "Failed to allocate input device.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ts->input_dev->name = "Goodix Capacitive TouchScreen";
|
||||
ts->input_dev->phys = "input/ts";
|
||||
ts->input_dev->id.bustype = BUS_I2C;
|
||||
ts->input_dev->id.vendor = 0x0416;
|
||||
ts->input_dev->id.product = ts->id;
|
||||
ts->input_dev->id.version = ts->version;
|
||||
|
||||
/* Capacitive Windows/Home button on some devices */
|
||||
input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
|
||||
|
||||
input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X);
|
||||
input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y);
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
|
||||
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
|
||||
|
||||
/* Read configuration and apply touchscreen parameters */
|
||||
goodix_read_config(ts);
|
||||
|
||||
error = goodix_request_input_dev(ts);
|
||||
if (error)
|
||||
/* Try overriding touchscreen parameters via device properties */
|
||||
touchscreen_parse_properties(ts->input_dev, true, &ts->prop);
|
||||
|
||||
if (!ts->prop.max_x || !ts->prop.max_y || !ts->max_touch_num) {
|
||||
dev_err(&ts->client->dev, "Invalid config, using defaults\n");
|
||||
ts->prop.max_x = GOODIX_MAX_WIDTH - 1;
|
||||
ts->prop.max_y = GOODIX_MAX_HEIGHT - 1;
|
||||
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
||||
input_abs_set_max(ts->input_dev,
|
||||
ABS_MT_POSITION_X, ts->prop.max_x);
|
||||
input_abs_set_max(ts->input_dev,
|
||||
ABS_MT_POSITION_Y, ts->prop.max_y);
|
||||
}
|
||||
|
||||
if (dmi_check_system(rotated_screen)) {
|
||||
ts->prop.invert_x = true;
|
||||
ts->prop.invert_y = true;
|
||||
dev_dbg(&ts->client->dev,
|
||||
"Applying '180 degrees rotated screen' quirk\n");
|
||||
}
|
||||
|
||||
error = input_mt_init_slots(ts->input_dev, ts->max_touch_num,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
"Failed to initialize MT slots: %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_device(ts->input_dev);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
"Failed to register input device: %d", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
|
||||
error = goodix_request_irq(ts);
|
||||
@@ -878,8 +853,10 @@ static int __maybe_unused goodix_suspend(struct device *dev)
|
||||
int error;
|
||||
|
||||
/* We need gpio pins to suspend/resume */
|
||||
if (!ts->gpiod_int || !ts->gpiod_rst)
|
||||
if (!ts->gpiod_int || !ts->gpiod_rst) {
|
||||
disable_irq(client->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wait_for_completion(&ts->firmware_loading_complete);
|
||||
|
||||
@@ -919,8 +896,10 @@ static int __maybe_unused goodix_resume(struct device *dev)
|
||||
struct goodix_ts_data *ts = i2c_get_clientdata(client);
|
||||
int error;
|
||||
|
||||
if (!ts->gpiod_int || !ts->gpiod_rst)
|
||||
if (!ts->gpiod_int || !ts->gpiod_rst) {
|
||||
enable_irq(client->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit sleep mode by outputting HIGH level to INT pin
|
||||
|
@@ -1611,6 +1611,5 @@ static struct i2c_driver mip4_driver = {
|
||||
module_i2c_driver(mip4_driver);
|
||||
|
||||
MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen");
|
||||
MODULE_VERSION("2016.10.31");
|
||||
MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -10,17 +10,18 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_data/mms114.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Write only registers */
|
||||
#define MMS114_MODE_CONTROL 0x01
|
||||
#define MMS114_OPERATION_MODE_MASK 0xE
|
||||
#define MMS114_ACTIVE (1 << 1)
|
||||
#define MMS114_ACTIVE BIT(1)
|
||||
|
||||
#define MMS114_XY_RESOLUTION_H 0x02
|
||||
#define MMS114_X_RESOLUTION 0x03
|
||||
@@ -30,9 +31,12 @@
|
||||
|
||||
/* Read only registers */
|
||||
#define MMS114_PACKET_SIZE 0x0F
|
||||
#define MMS114_INFOMATION 0x10
|
||||
#define MMS114_INFORMATION 0x10
|
||||
#define MMS114_TSP_REV 0xF0
|
||||
|
||||
#define MMS152_FW_REV 0xE1
|
||||
#define MMS152_COMPAT_GROUP 0xF2
|
||||
|
||||
/* Minimum delay time is 50us between stop and start signal of i2c */
|
||||
#define MMS114_I2C_DELAY 50
|
||||
|
||||
@@ -50,12 +54,20 @@
|
||||
#define MMS114_TYPE_TOUCHSCREEN 1
|
||||
#define MMS114_TYPE_TOUCHKEY 2
|
||||
|
||||
enum mms_type {
|
||||
TYPE_MMS114 = 114,
|
||||
TYPE_MMS152 = 152,
|
||||
};
|
||||
|
||||
struct mms114_data {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
struct regulator *core_reg;
|
||||
struct regulator *io_reg;
|
||||
const struct mms114_platform_data *pdata;
|
||||
struct touchscreen_properties props;
|
||||
enum mms_type type;
|
||||
unsigned int contact_threshold;
|
||||
unsigned int moving_threshold;
|
||||
|
||||
/* Use cache data for mode control register(write only) */
|
||||
u8 cache_mode_control;
|
||||
@@ -143,7 +155,6 @@ static int mms114_write_reg(struct mms114_data *data, unsigned int reg,
|
||||
|
||||
static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch)
|
||||
{
|
||||
const struct mms114_platform_data *pdata = data->pdata;
|
||||
struct i2c_client *client = data->client;
|
||||
struct input_dev *input_dev = data->input_dev;
|
||||
unsigned int id;
|
||||
@@ -163,16 +174,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
|
||||
id = touch->id - 1;
|
||||
x = touch->x_lo | touch->x_hi << 8;
|
||||
y = touch->y_lo | touch->y_hi << 8;
|
||||
if (x > pdata->x_size || y > pdata->y_size) {
|
||||
dev_dbg(&client->dev,
|
||||
"Wrong touch coordinates (%d, %d)\n", x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pdata->x_invert)
|
||||
x = pdata->x_size - x;
|
||||
if (pdata->y_invert)
|
||||
y = pdata->y_size - y;
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n",
|
||||
@@ -183,9 +184,8 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
|
||||
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed);
|
||||
|
||||
if (touch->pressed) {
|
||||
touchscreen_report_pos(input_dev, &data->props, x, y, true);
|
||||
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
|
||||
input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength);
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
|
||||
|
||||
touch_size = packet_size / MMS114_PACKET_NUM;
|
||||
|
||||
error = __mms114_read_reg(data, MMS114_INFOMATION, packet_size,
|
||||
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
|
||||
(u8 *)touch);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
@@ -249,21 +249,40 @@ static int mms114_get_version(struct mms114_data *data)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
u8 buf[6];
|
||||
int group;
|
||||
int error;
|
||||
|
||||
error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
|
||||
if (error < 0)
|
||||
return error;
|
||||
switch (data->type) {
|
||||
case TYPE_MMS152:
|
||||
error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
|
||||
buf[0], buf[1], buf[3]);
|
||||
group = i2c_smbus_read_byte_data(data->client,
|
||||
MMS152_COMPAT_GROUP);
|
||||
if (group < 0)
|
||||
return group;
|
||||
|
||||
dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
|
||||
buf[0], buf[1], buf[2], group);
|
||||
break;
|
||||
|
||||
case TYPE_MMS114:
|
||||
error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
|
||||
buf[0], buf[1], buf[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mms114_setup_regs(struct mms114_data *data)
|
||||
{
|
||||
const struct mms114_platform_data *pdata = data->pdata;
|
||||
const struct touchscreen_properties *props = &data->props;
|
||||
int val;
|
||||
int error;
|
||||
|
||||
@@ -271,36 +290,40 @@ static int mms114_setup_regs(struct mms114_data *data)
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
/* MMS152 has no configuration or power on registers */
|
||||
if (data->type == TYPE_MMS152)
|
||||
return 0;
|
||||
|
||||
error = mms114_set_active(data, true);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
val = (pdata->x_size >> 8) & 0xf;
|
||||
val |= ((pdata->y_size >> 8) & 0xf) << 4;
|
||||
val = (props->max_x >> 8) & 0xf;
|
||||
val |= ((props->max_y >> 8) & 0xf) << 4;
|
||||
error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
val = pdata->x_size & 0xff;
|
||||
val = props->max_x & 0xff;
|
||||
error = mms114_write_reg(data, MMS114_X_RESOLUTION, val);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
val = pdata->y_size & 0xff;
|
||||
val = props->max_x & 0xff;
|
||||
error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (pdata->contact_threshold) {
|
||||
if (data->contact_threshold) {
|
||||
error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD,
|
||||
pdata->contact_threshold);
|
||||
data->contact_threshold);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (pdata->moving_threshold) {
|
||||
if (data->moving_threshold) {
|
||||
error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD,
|
||||
pdata->moving_threshold);
|
||||
data->moving_threshold);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
@@ -326,7 +349,7 @@ static int mms114_start(struct mms114_data *data)
|
||||
return error;
|
||||
}
|
||||
|
||||
mdelay(MMS114_POWERON_DELAY);
|
||||
msleep(MMS114_POWERON_DELAY);
|
||||
|
||||
error = mms114_setup_regs(data);
|
||||
if (error < 0) {
|
||||
@@ -335,9 +358,6 @@ static int mms114_start(struct mms114_data *data)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (data->pdata->cfg_pin)
|
||||
data->pdata->cfg_pin(true);
|
||||
|
||||
enable_irq(client->irq);
|
||||
|
||||
return 0;
|
||||
@@ -350,9 +370,6 @@ static void mms114_stop(struct mms114_data *data)
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (data->pdata->cfg_pin)
|
||||
data->pdata->cfg_pin(false);
|
||||
|
||||
error = regulator_disable(data->io_reg);
|
||||
if (error)
|
||||
dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
|
||||
@@ -376,67 +393,44 @@ static void mms114_input_close(struct input_dev *dev)
|
||||
mms114_stop(data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
|
||||
static int mms114_parse_legacy_bindings(struct mms114_data *data)
|
||||
{
|
||||
struct mms114_platform_data *pdata;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device *dev = &data->client->dev;
|
||||
struct touchscreen_properties *props = &data->props;
|
||||
|
||||
if (!np)
|
||||
return NULL;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(dev, "failed to allocate platform data\n");
|
||||
return NULL;
|
||||
if (device_property_read_u32(dev, "x-size", &props->max_x)) {
|
||||
dev_dbg(dev, "failed to get legacy x-size property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
|
||||
dev_err(dev, "failed to get x-size property\n");
|
||||
return NULL;
|
||||
if (device_property_read_u32(dev, "y-size", &props->max_y)) {
|
||||
dev_dbg(dev, "failed to get legacy y-size property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
|
||||
dev_err(dev, "failed to get y-size property\n");
|
||||
return NULL;
|
||||
}
|
||||
device_property_read_u32(dev, "contact-threshold",
|
||||
&data->contact_threshold);
|
||||
device_property_read_u32(dev, "moving-threshold",
|
||||
&data->moving_threshold);
|
||||
|
||||
of_property_read_u32(np, "contact-threshold",
|
||||
&pdata->contact_threshold);
|
||||
of_property_read_u32(np, "moving-threshold",
|
||||
&pdata->moving_threshold);
|
||||
if (device_property_read_bool(dev, "x-invert"))
|
||||
props->invert_x = true;
|
||||
if (device_property_read_bool(dev, "y-invert"))
|
||||
props->invert_y = true;
|
||||
|
||||
if (of_find_property(np, "x-invert", NULL))
|
||||
pdata->x_invert = true;
|
||||
if (of_find_property(np, "y-invert", NULL))
|
||||
pdata->y_invert = true;
|
||||
props->swap_x_y = false;
|
||||
|
||||
return pdata;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mms114_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct mms114_platform_data *pdata;
|
||||
struct mms114_data *data;
|
||||
struct input_dev *input_dev;
|
||||
const void *match_data;
|
||||
int error;
|
||||
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (!pdata)
|
||||
pdata = mms114_parse_dt(&client->dev);
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "Need platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_PROTOCOL_MANGLING)) {
|
||||
dev_err(&client->dev,
|
||||
@@ -454,29 +448,63 @@ static int mms114_probe(struct i2c_client *client,
|
||||
|
||||
data->client = client;
|
||||
data->input_dev = input_dev;
|
||||
data->pdata = pdata;
|
||||
|
||||
input_dev->name = "MELFAS MMS114 Touchscreen";
|
||||
/* FIXME: switch to device_get_match_data() when available */
|
||||
match_data = of_device_get_match_data(&client->dev);
|
||||
if (!match_data)
|
||||
return -EINVAL;
|
||||
|
||||
data->type = (enum mms_type)match_data;
|
||||
|
||||
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
|
||||
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
|
||||
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
0, MMS114_MAX_AREA, 0, 0);
|
||||
|
||||
touchscreen_parse_properties(input_dev, true, &data->props);
|
||||
if (!data->props.max_x || !data->props.max_y) {
|
||||
dev_dbg(&client->dev,
|
||||
"missing X/Y size properties, trying legacy bindings\n");
|
||||
error = mms114_parse_legacy_bindings(data);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, data->props.max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
0, data->props.max_y, 0, 0);
|
||||
}
|
||||
|
||||
if (data->type == TYPE_MMS114) {
|
||||
/*
|
||||
* The firmware handles movement and pressure fuzz, so
|
||||
* don't duplicate that in software.
|
||||
*/
|
||||
data->moving_threshold = input_abs_get_fuzz(input_dev,
|
||||
ABS_MT_POSITION_X);
|
||||
data->contact_threshold = input_abs_get_fuzz(input_dev,
|
||||
ABS_MT_PRESSURE);
|
||||
input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
|
||||
input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
|
||||
input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
|
||||
}
|
||||
|
||||
input_dev->name = devm_kasprintf(&client->dev, GFP_KERNEL,
|
||||
"MELFAS MMS%d Touchscreen",
|
||||
data->type);
|
||||
if (!input_dev->name)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = &client->dev;
|
||||
input_dev->open = mms114_input_open;
|
||||
input_dev->close = mms114_input_close;
|
||||
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, data->pdata->x_size, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0);
|
||||
|
||||
/* For multi touch */
|
||||
input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
0, MMS114_MAX_AREA, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, data->pdata->x_size, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
0, data->pdata->y_size, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
||||
error = input_mt_init_slots(input_dev, MMS114_MAX_TOUCH,
|
||||
INPUT_MT_DIRECT);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
input_set_drvdata(input_dev, data);
|
||||
i2c_set_clientdata(client, data);
|
||||
@@ -497,9 +525,9 @@ static int mms114_probe(struct i2c_client *client,
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
|
||||
mms114_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
dev_name(&client->dev), data);
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, mms114_interrupt, IRQF_ONESHOT,
|
||||
dev_name(&client->dev), data);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to register interrupt\n");
|
||||
return error;
|
||||
@@ -569,7 +597,13 @@ MODULE_DEVICE_TABLE(i2c, mms114_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id mms114_dt_match[] = {
|
||||
{ .compatible = "melfas,mms114" },
|
||||
{
|
||||
.compatible = "melfas,mms114",
|
||||
.data = (void *)TYPE_MMS114,
|
||||
}, {
|
||||
.compatible = "melfas,mms152",
|
||||
.data = (void *)TYPE_MMS152,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mms114_dt_match);
|
||||
|
@@ -752,13 +752,20 @@ static int raydium_i2c_fw_update(struct raydium_data *ts)
|
||||
{
|
||||
struct i2c_client *client = ts->client;
|
||||
const struct firmware *fw = NULL;
|
||||
const char *fw_file = "raydium.fw";
|
||||
char *fw_file;
|
||||
int error;
|
||||
|
||||
fw_file = kasprintf(GFP_KERNEL, "raydium_%#04x.fw",
|
||||
le32_to_cpu(ts->info.hw_ver));
|
||||
if (!fw_file)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_dbg(&client->dev, "firmware name: %s\n", fw_file);
|
||||
|
||||
error = request_firmware(&fw, fw_file, &client->dev);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Unable to open firmware %s\n", fw_file);
|
||||
return error;
|
||||
goto out_free_fw_file;
|
||||
}
|
||||
|
||||
disable_irq(client->irq);
|
||||
@@ -787,6 +794,9 @@ out_enable_irq:
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
out_free_fw_file:
|
||||
kfree(fw_file);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@@ -56,7 +56,7 @@
|
||||
#define SILEAD_POINT_Y_MSB_OFF 0x01
|
||||
#define SILEAD_POINT_X_OFF 0x02
|
||||
#define SILEAD_POINT_X_MSB_OFF 0x03
|
||||
#define SILEAD_TOUCH_ID_MASK 0xF0
|
||||
#define SILEAD_EXTRA_DATA_MASK 0xF0
|
||||
|
||||
#define SILEAD_CMD_SLEEP_MIN 10000
|
||||
#define SILEAD_CMD_SLEEP_MAX 20000
|
||||
@@ -109,6 +109,9 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
|
||||
INPUT_MT_TRACK);
|
||||
|
||||
if (device_property_read_bool(dev, "silead,home-button"))
|
||||
input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);
|
||||
|
||||
data->input->name = SILEAD_TS_NAME;
|
||||
data->input->phys = "input/ts";
|
||||
data->input->id.bustype = BUS_I2C;
|
||||
@@ -139,7 +142,8 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
struct input_dev *input = data->input;
|
||||
struct device *dev = &client->dev;
|
||||
u8 *bufp, buf[SILEAD_TS_DATA_LEN];
|
||||
int touch_nr, error, i;
|
||||
int touch_nr, softbutton, error, i;
|
||||
bool softbutton_pressed = false;
|
||||
|
||||
error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
|
||||
SILEAD_TS_DATA_LEN, buf);
|
||||
@@ -148,21 +152,40 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
return;
|
||||
}
|
||||
|
||||
touch_nr = buf[0];
|
||||
if (touch_nr > data->max_fingers) {
|
||||
if (buf[0] > data->max_fingers) {
|
||||
dev_warn(dev, "More touches reported then supported %d > %d\n",
|
||||
touch_nr, data->max_fingers);
|
||||
touch_nr = data->max_fingers;
|
||||
buf[0], data->max_fingers);
|
||||
buf[0] = data->max_fingers;
|
||||
}
|
||||
|
||||
touch_nr = 0;
|
||||
bufp = buf + SILEAD_POINT_DATA_LEN;
|
||||
for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) {
|
||||
/* Bits 4-7 are the touch id */
|
||||
data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] &
|
||||
SILEAD_TOUCH_ID_MASK) >> 4;
|
||||
touchscreen_set_mt_pos(&data->pos[i], &data->prop,
|
||||
for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) {
|
||||
softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] &
|
||||
SILEAD_EXTRA_DATA_MASK) >> 4;
|
||||
|
||||
if (softbutton) {
|
||||
/*
|
||||
* For now only respond to softbutton == 0x01, some
|
||||
* tablets *without* a capacative button send 0x04
|
||||
* when crossing the edges of the screen.
|
||||
*/
|
||||
if (softbutton == 0x01)
|
||||
softbutton_pressed = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bits 4-7 are the touch id, note not all models have
|
||||
* hardware touch ids so atm we don't use these.
|
||||
*/
|
||||
data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] &
|
||||
SILEAD_EXTRA_DATA_MASK) >> 4;
|
||||
touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop,
|
||||
get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
|
||||
get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
|
||||
touch_nr++;
|
||||
}
|
||||
|
||||
input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
|
||||
@@ -178,6 +201,7 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
}
|
||||
|
||||
input_mt_sync_frame(input);
|
||||
input_report_key(input, KEY_LEFTMETA, softbutton_pressed);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
|
@@ -682,6 +682,14 @@ static int stmfts_probe(struct i2c_client *client,
|
||||
|
||||
input_set_drvdata(sdata->input, sdata);
|
||||
|
||||
/*
|
||||
* stmfts_power_on expects interrupt to be disabled, but
|
||||
* at this point the device is still off and I do not trust
|
||||
* the status of the irq line that can generate some spurious
|
||||
* interrupts. To be on the safe side it's better to not enable
|
||||
* the interrupts during their request.
|
||||
*/
|
||||
irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, stmfts_irq_handler,
|
||||
IRQF_ONESHOT,
|
||||
@@ -689,9 +697,6 @@ static int stmfts_probe(struct i2c_client *client,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* stmfts_power_on expects interrupt to be disabled */
|
||||
disable_irq(client->irq);
|
||||
|
||||
dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
|
||||
|
||||
err = stmfts_power_on(sdata);
|
||||
|
@@ -55,11 +55,6 @@
|
||||
#include <linux/usb/input.h>
|
||||
#include <linux/hid.h>
|
||||
|
||||
|
||||
#define DRIVER_VERSION "v0.6"
|
||||
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
|
||||
#define DRIVER_DESC "USB Touchscreen Driver"
|
||||
|
||||
static bool swap_xy;
|
||||
module_param(swap_xy, bool, 0644);
|
||||
MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
|
||||
@@ -1763,8 +1758,8 @@ static struct usb_driver usbtouch_driver = {
|
||||
|
||||
module_usb_driver(usbtouch_driver);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("Daniel Ritz <daniel.ritz@gmx.ch>");
|
||||
MODULE_DESCRIPTION("USB Touchscreen Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_ALIAS("touchkitusb");
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define WDT87XX_NAME "wdt87xx_i2c"
|
||||
#define WDT87XX_DRV_VER "0.9.8"
|
||||
#define WDT87XX_FW_NAME "wdt87xx_fw.bin"
|
||||
#define WDT87XX_CFG_NAME "wdt87xx_cfg.bin"
|
||||
|
||||
@@ -1183,5 +1182,4 @@ module_i2c_driver(wdt87xx_driver);
|
||||
|
||||
MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>");
|
||||
MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver");
|
||||
MODULE_VERSION(WDT87XX_DRV_VER);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Reference in New Issue
Block a user