Merge branch 'next' into for-linus
This commit is contained in:
@@ -248,6 +248,18 @@ config TOUCHSCREEN_LPC32XX
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called lpc32xx_ts.
|
||||
|
||||
config TOUCHSCREEN_MAX11801
|
||||
tristate "MAX11801 based touchscreens"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MAX11801 based touchscreen
|
||||
controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called max11801_ts.
|
||||
|
||||
config TOUCHSCREEN_MCS5000
|
||||
tristate "MELFAS MCS-5000 touchscreen"
|
||||
depends on I2C
|
||||
|
@@ -27,6 +27,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
|
||||
|
@@ -109,6 +109,7 @@ struct ads7846 {
|
||||
u16 pressure_max;
|
||||
|
||||
bool swap_xy;
|
||||
bool use_internal;
|
||||
|
||||
struct ads7846_packet *packet;
|
||||
|
||||
@@ -307,7 +308,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
|
||||
struct ads7846 *ts = dev_get_drvdata(dev);
|
||||
struct ser_req *req;
|
||||
int status;
|
||||
int use_internal;
|
||||
|
||||
req = kzalloc(sizeof *req, GFP_KERNEL);
|
||||
if (!req)
|
||||
@@ -315,11 +315,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
|
||||
|
||||
spi_message_init(&req->msg);
|
||||
|
||||
/* FIXME boards with ads7846 might use external vref instead ... */
|
||||
use_internal = (ts->model == 7846);
|
||||
|
||||
/* maybe turn on internal vREF, and let it settle */
|
||||
if (use_internal) {
|
||||
if (ts->use_internal) {
|
||||
req->ref_on = REF_ON;
|
||||
req->xfer[0].tx_buf = &req->ref_on;
|
||||
req->xfer[0].len = 1;
|
||||
@@ -331,8 +328,14 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
|
||||
/* for 1uF, settle for 800 usec; no cap, 100 usec. */
|
||||
req->xfer[1].delay_usecs = ts->vref_delay_usecs;
|
||||
spi_message_add_tail(&req->xfer[1], &req->msg);
|
||||
|
||||
/* Enable reference voltage */
|
||||
command |= ADS_PD10_REF_ON;
|
||||
}
|
||||
|
||||
/* Enable ADC in every case */
|
||||
command |= ADS_PD10_ADC_ON;
|
||||
|
||||
/* take sample */
|
||||
req->command = (u8) command;
|
||||
req->xfer[2].tx_buf = &req->command;
|
||||
@@ -416,7 +419,7 @@ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct ads7846 *ts = dev_get_drvdata(dev); \
|
||||
ssize_t v = ads7846_read12_ser(dev, \
|
||||
READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \
|
||||
READ_12BIT_SER(var)); \
|
||||
if (v < 0) \
|
||||
return v; \
|
||||
return sprintf(buf, "%u\n", adjust(ts, v)); \
|
||||
@@ -509,6 +512,7 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
|
||||
if (!ts->vref_mv) {
|
||||
dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
|
||||
ts->vref_mv = 2500;
|
||||
ts->use_internal = true;
|
||||
}
|
||||
break;
|
||||
case 7845:
|
||||
@@ -969,6 +973,13 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
|
||||
pdata->gpio_pendown);
|
||||
return err;
|
||||
}
|
||||
err = gpio_direction_input(pdata->gpio_pendown);
|
||||
if (err) {
|
||||
dev_err(&spi->dev, "failed to setup pendown GPIO%d\n",
|
||||
pdata->gpio_pendown);
|
||||
gpio_free(pdata->gpio_pendown);
|
||||
return err;
|
||||
}
|
||||
|
||||
ts->gpio_pendown = pdata->gpio_pendown;
|
||||
|
||||
@@ -1340,8 +1351,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
||||
if (ts->model == 7845)
|
||||
ads7845_read12_ser(&spi->dev, PWRDOWN);
|
||||
else
|
||||
(void) ads7846_read12_ser(&spi->dev,
|
||||
READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
|
||||
(void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux));
|
||||
|
||||
err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group);
|
||||
if (err)
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/atmel_mxt_ts.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -196,9 +196,12 @@
|
||||
#define MXT_PRESS (1 << 6)
|
||||
#define MXT_DETECT (1 << 7)
|
||||
|
||||
/* Touch orient bits */
|
||||
#define MXT_XY_SWITCH (1 << 0)
|
||||
#define MXT_X_INVERT (1 << 1)
|
||||
#define MXT_Y_INVERT (1 << 2)
|
||||
|
||||
/* Touchscreen absolute values */
|
||||
#define MXT_MAX_XC 0x3ff
|
||||
#define MXT_MAX_YC 0x3ff
|
||||
#define MXT_MAX_AREA 0xff
|
||||
|
||||
#define MXT_MAX_FINGER 10
|
||||
@@ -246,6 +249,8 @@ struct mxt_data {
|
||||
struct mxt_info info;
|
||||
struct mxt_finger finger[MXT_MAX_FINGER];
|
||||
unsigned int irq;
|
||||
unsigned int max_x;
|
||||
unsigned int max_y;
|
||||
};
|
||||
|
||||
static bool mxt_object_readable(unsigned int type)
|
||||
@@ -499,19 +504,21 @@ static void mxt_input_report(struct mxt_data *data, int single_id)
|
||||
if (!finger[id].status)
|
||||
continue;
|
||||
|
||||
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
finger[id].status != MXT_RELEASE ?
|
||||
finger[id].area : 0);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_X,
|
||||
finger[id].x);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_Y,
|
||||
finger[id].y);
|
||||
input_mt_sync(input_dev);
|
||||
input_mt_slot(input_dev, id);
|
||||
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
|
||||
finger[id].status != MXT_RELEASE);
|
||||
|
||||
if (finger[id].status == MXT_RELEASE)
|
||||
finger[id].status = 0;
|
||||
else
|
||||
if (finger[id].status != MXT_RELEASE) {
|
||||
finger_num++;
|
||||
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
finger[id].area);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_X,
|
||||
finger[id].x);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_Y,
|
||||
finger[id].y);
|
||||
} else {
|
||||
finger[id].status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
|
||||
@@ -549,8 +556,13 @@ static void mxt_input_touchevent(struct mxt_data *data,
|
||||
if (!(status & (MXT_PRESS | MXT_MOVE)))
|
||||
return;
|
||||
|
||||
x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
|
||||
y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
|
||||
x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
|
||||
y = (message->message[2] << 4) | ((message->message[3] & 0xf));
|
||||
if (data->max_x < 1024)
|
||||
x = x >> 2;
|
||||
if (data->max_y < 1024)
|
||||
y = y >> 2;
|
||||
|
||||
area = message->message[4];
|
||||
|
||||
dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
|
||||
@@ -804,10 +816,6 @@ static int mxt_initialize(struct mxt_data *data)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = mxt_make_highchg(data);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mxt_handle_pdata(data);
|
||||
|
||||
/* Backup to memory */
|
||||
@@ -845,6 +853,20 @@ static int mxt_initialize(struct mxt_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxt_calc_resolution(struct mxt_data *data)
|
||||
{
|
||||
unsigned int max_x = data->pdata->x_size - 1;
|
||||
unsigned int max_y = data->pdata->y_size - 1;
|
||||
|
||||
if (data->pdata->orient & MXT_XY_SWITCH) {
|
||||
data->max_x = max_y;
|
||||
data->max_y = max_x;
|
||||
} else {
|
||||
data->max_x = max_x;
|
||||
data->max_y = max_y;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t mxt_object_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -981,6 +1003,10 @@ static ssize_t mxt_update_fw_store(struct device *dev,
|
||||
|
||||
enable_irq(data->irq);
|
||||
|
||||
error = mxt_make_highchg(data);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -1052,31 +1078,33 @@ static int __devinit mxt_probe(struct i2c_client *client,
|
||||
input_dev->open = mxt_input_open;
|
||||
input_dev->close = mxt_input_close;
|
||||
|
||||
data->client = client;
|
||||
data->input_dev = input_dev;
|
||||
data->pdata = pdata;
|
||||
data->irq = client->irq;
|
||||
|
||||
mxt_calc_resolution(data);
|
||||
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
|
||||
/* For single touch */
|
||||
input_set_abs_params(input_dev, ABS_X,
|
||||
0, MXT_MAX_XC, 0, 0);
|
||||
0, data->max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y,
|
||||
0, MXT_MAX_YC, 0, 0);
|
||||
0, data->max_y, 0, 0);
|
||||
|
||||
/* For multi touch */
|
||||
input_mt_init_slots(input_dev, MXT_MAX_FINGER);
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
0, MXT_MAX_AREA, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, MXT_MAX_XC, 0, 0);
|
||||
0, data->max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
|
||||
0, MXT_MAX_YC, 0, 0);
|
||||
0, data->max_y, 0, 0);
|
||||
|
||||
input_set_drvdata(input_dev, data);
|
||||
|
||||
data->client = client;
|
||||
data->input_dev = input_dev;
|
||||
data->pdata = pdata;
|
||||
data->irq = client->irq;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
error = mxt_initialize(data);
|
||||
@@ -1090,6 +1118,10 @@ static int __devinit mxt_probe(struct i2c_client *client,
|
||||
goto err_free_object;
|
||||
}
|
||||
|
||||
error = mxt_make_highchg(data);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
|
@@ -317,7 +317,7 @@ err_unmap_regs:
|
||||
err_release_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free_dev:
|
||||
input_free_device(ts_dev->input);
|
||||
input_free_device(input_dev);
|
||||
err_free_mem:
|
||||
kfree(ts_dev);
|
||||
return err;
|
||||
|
@@ -396,14 +396,14 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
|
||||
set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
|
||||
|
||||
if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
|
||||
IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) {
|
||||
IRQF_SHARED | IRQF_DISABLED, "h3600_action", ts->dev)) {
|
||||
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
|
||||
err = -EBUSY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
|
||||
IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) {
|
||||
IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", ts->dev)) {
|
||||
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
|
||||
err = -EBUSY;
|
||||
goto fail2;
|
||||
@@ -439,8 +439,8 @@ static void h3600ts_disconnect(struct serio *serio)
|
||||
{
|
||||
struct h3600_dev *ts = serio_get_drvdata(serio);
|
||||
|
||||
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
|
||||
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
|
||||
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
|
||||
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
|
||||
input_get_device(ts->dev);
|
||||
input_unregister_device(ts->dev);
|
||||
serio_close(serio);
|
||||
|
@@ -542,7 +542,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
|
||||
* ADC power on, start, enable PENDET and set loop delay
|
||||
* ADC loop delay is set to 4.5 ms approximately
|
||||
* Loop delay more than this results in jitter in adc readings
|
||||
* Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
|
||||
* Setting loop delay to 0 (continuous loop) in MAXIM stops PENDET
|
||||
* interrupt generation sometimes.
|
||||
*/
|
||||
|
||||
|
@@ -219,7 +219,7 @@ static int wm97xx_acc_startup(struct wm97xx *wm)
|
||||
}
|
||||
|
||||
wm->pen_irq = gpio_to_irq(irq);
|
||||
set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
|
||||
irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
|
||||
} else /* pen irq not supported */
|
||||
pen_int = 0;
|
||||
|
||||
|
272
drivers/input/touchscreen/max11801_ts.c
Normal file
272
drivers/input/touchscreen/max11801_ts.c
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Driver for MAXI MAX11801 - A Resistive touch screen controller with
|
||||
* i2c interface
|
||||
*
|
||||
* Copyright (C) 2011 Freescale Semiconductor, Inc.
|
||||
* Author: Zhang Jiejing <jiejing.zhang@freescale.com>
|
||||
*
|
||||
* Based on mcs5000_ts.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This driver aims to support the series of MAXI touch chips max11801
|
||||
* through max11803. The main difference between these 4 chips can be
|
||||
* found in the table below:
|
||||
* -----------------------------------------------------
|
||||
* | CHIP | AUTO MODE SUPPORT(FIFO) | INTERFACE |
|
||||
* |----------------------------------------------------|
|
||||
* | max11800 | YES | SPI |
|
||||
* | max11801 | YES | I2C |
|
||||
* | max11802 | NO | SPI |
|
||||
* | max11803 | NO | I2C |
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Currently, this driver only supports max11801.
|
||||
*
|
||||
* Data Sheet:
|
||||
* http://www.maxim-ic.com/datasheet/index.mvp/id/5943
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
/* Register Address define */
|
||||
#define GENERNAL_STATUS_REG 0x00
|
||||
#define GENERNAL_CONF_REG 0x01
|
||||
#define MESURE_RES_CONF_REG 0x02
|
||||
#define MESURE_AVER_CONF_REG 0x03
|
||||
#define ADC_SAMPLE_TIME_CONF_REG 0x04
|
||||
#define PANEL_SETUPTIME_CONF_REG 0x05
|
||||
#define DELAY_CONVERSION_CONF_REG 0x06
|
||||
#define TOUCH_DETECT_PULLUP_CONF_REG 0x07
|
||||
#define AUTO_MODE_TIME_CONF_REG 0x08 /* only for max11800/max11801 */
|
||||
#define APERTURE_CONF_REG 0x09 /* only for max11800/max11801 */
|
||||
#define AUX_MESURE_CONF_REG 0x0a
|
||||
#define OP_MODE_CONF_REG 0x0b
|
||||
|
||||
/* FIFO is found only in max11800 and max11801 */
|
||||
#define FIFO_RD_CMD (0x50 << 1)
|
||||
#define MAX11801_FIFO_INT (1 << 2)
|
||||
#define MAX11801_FIFO_OVERFLOW (1 << 3)
|
||||
|
||||
#define XY_BUFSIZE 4
|
||||
#define XY_BUF_OFFSET 4
|
||||
|
||||
#define MAX11801_MAX_X 0xfff
|
||||
#define MAX11801_MAX_Y 0xfff
|
||||
|
||||
#define MEASURE_TAG_OFFSET 2
|
||||
#define MEASURE_TAG_MASK (3 << MEASURE_TAG_OFFSET)
|
||||
#define EVENT_TAG_OFFSET 0
|
||||
#define EVENT_TAG_MASK (3 << EVENT_TAG_OFFSET)
|
||||
#define MEASURE_X_TAG (0 << MEASURE_TAG_OFFSET)
|
||||
#define MEASURE_Y_TAG (1 << MEASURE_TAG_OFFSET)
|
||||
|
||||
/* These are the state of touch event state machine */
|
||||
enum {
|
||||
EVENT_INIT,
|
||||
EVENT_MIDDLE,
|
||||
EVENT_RELEASE,
|
||||
EVENT_FIFO_END
|
||||
};
|
||||
|
||||
struct max11801_data {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
};
|
||||
|
||||
static u8 read_register(struct i2c_client *client, int addr)
|
||||
{
|
||||
/* XXX: The chip ignores LSB of register address */
|
||||
return i2c_smbus_read_byte_data(client, addr << 1);
|
||||
}
|
||||
|
||||
static int max11801_write_reg(struct i2c_client *client, int addr, int data)
|
||||
{
|
||||
/* XXX: The chip ignores LSB of register address */
|
||||
return i2c_smbus_write_byte_data(client, addr << 1, data);
|
||||
}
|
||||
|
||||
static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct max11801_data *data = dev_id;
|
||||
struct i2c_client *client = data->client;
|
||||
int status, i, ret;
|
||||
u8 buf[XY_BUFSIZE];
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
|
||||
status = read_register(data->client, GENERNAL_STATUS_REG);
|
||||
|
||||
if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
|
||||
status = read_register(data->client, GENERNAL_STATUS_REG);
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
|
||||
XY_BUFSIZE, buf);
|
||||
|
||||
/*
|
||||
* We should get 4 bytes buffer that contains X,Y
|
||||
* and event tag
|
||||
*/
|
||||
if (ret < XY_BUFSIZE)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
|
||||
if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
|
||||
x = (buf[i] << XY_BUF_OFFSET) +
|
||||
(buf[i + 1] >> XY_BUF_OFFSET);
|
||||
else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
|
||||
y = (buf[i] << XY_BUF_OFFSET) +
|
||||
(buf[i + 1] >> XY_BUF_OFFSET);
|
||||
}
|
||||
|
||||
if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
|
||||
goto out;
|
||||
|
||||
switch (buf[1] & EVENT_TAG_MASK) {
|
||||
case EVENT_INIT:
|
||||
/* fall through */
|
||||
case EVENT_MIDDLE:
|
||||
input_report_abs(data->input_dev, ABS_X, x);
|
||||
input_report_abs(data->input_dev, ABS_Y, y);
|
||||
input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
|
||||
input_sync(data->input_dev);
|
||||
break;
|
||||
|
||||
case EVENT_RELEASE:
|
||||
input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
|
||||
input_sync(data->input_dev);
|
||||
break;
|
||||
|
||||
case EVENT_FIFO_END:
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void __devinit max11801_ts_phy_init(struct max11801_data *data)
|
||||
{
|
||||
struct i2c_client *client = data->client;
|
||||
|
||||
/* Average X,Y, take 16 samples, average eight media sample */
|
||||
max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
|
||||
/* X,Y panel setup time set to 20us */
|
||||
max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
|
||||
/* Rough pullup time (2uS), Fine pullup time (10us) */
|
||||
max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
|
||||
/* Auto mode init period = 5ms , scan period = 5ms*/
|
||||
max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
|
||||
/* Aperture X,Y set to +- 4LSB */
|
||||
max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
|
||||
/* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
|
||||
max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
|
||||
}
|
||||
|
||||
static int __devinit max11801_ts_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max11801_data *data;
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
data = kzalloc(sizeof(struct max11801_data), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!data || !input_dev) {
|
||||
dev_err(&client->dev, "Failed to allocate memory\n");
|
||||
error = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
data->client = client;
|
||||
data->input_dev = input_dev;
|
||||
|
||||
input_dev->name = "max11801_ts";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = &client->dev;
|
||||
|
||||
__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, MAX11801_MAX_X, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, MAX11801_MAX_Y, 0, 0);
|
||||
input_set_drvdata(input_dev, data);
|
||||
|
||||
max11801_ts_phy_init(data);
|
||||
|
||||
error = request_threaded_irq(client->irq, NULL, max11801_ts_interrupt,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"max11801_ts", data);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to register interrupt\n");
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
error = input_register_device(data->input_dev);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(client->irq, data);
|
||||
err_free_mem:
|
||||
input_free_device(input_dev);
|
||||
kfree(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
static __devexit int max11801_ts_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max11801_data *data = i2c_get_clientdata(client);
|
||||
|
||||
free_irq(client->irq, data);
|
||||
input_unregister_device(data->input_dev);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max11801_ts_id[] = {
|
||||
{"max11801", 0},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
|
||||
|
||||
static struct i2c_driver max11801_ts_driver = {
|
||||
.driver = {
|
||||
.name = "max11801_ts",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = max11801_ts_id,
|
||||
.probe = max11801_ts_probe,
|
||||
.remove = __devexit_p(max11801_ts_remove),
|
||||
};
|
||||
|
||||
static int __init max11801_ts_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max11801_ts_driver);
|
||||
}
|
||||
|
||||
static void __exit max11801_ts_exit(void)
|
||||
{
|
||||
i2c_del_driver(&max11801_ts_driver);
|
||||
}
|
||||
|
||||
module_init(max11801_ts_init);
|
||||
module_exit(max11801_ts_exit);
|
||||
|
||||
MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
|
||||
MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller");
|
||||
MODULE_LICENSE("GPL");
|
@@ -43,7 +43,6 @@ struct tps6507x_ts {
|
||||
struct input_dev *input_dev;
|
||||
struct device *dev;
|
||||
char phys[32];
|
||||
struct workqueue_struct *wq;
|
||||
struct delayed_work work;
|
||||
unsigned polling; /* polling is active */
|
||||
struct ts_event tc;
|
||||
@@ -220,8 +219,8 @@ done:
|
||||
poll = 1;
|
||||
|
||||
if (poll) {
|
||||
schd = queue_delayed_work(tsc->wq, &tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
schd = schedule_delayed_work(&tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
if (schd)
|
||||
tsc->polling = 1;
|
||||
else {
|
||||
@@ -303,7 +302,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
tsc->input_dev = input_dev;
|
||||
|
||||
INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
|
||||
tsc->wq = create_workqueue("TPS6507x Touchscreen");
|
||||
|
||||
if (init_data) {
|
||||
tsc->poll_period = init_data->poll_period;
|
||||
@@ -325,8 +323,8 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
goto err2;
|
||||
|
||||
schd = queue_delayed_work(tsc->wq, &tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
schd = schedule_delayed_work(&tsc->work,
|
||||
msecs_to_jiffies(tsc->poll_period));
|
||||
|
||||
if (schd)
|
||||
tsc->polling = 1;
|
||||
@@ -341,7 +339,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
|
||||
err2:
|
||||
cancel_delayed_work_sync(&tsc->work);
|
||||
destroy_workqueue(tsc->wq);
|
||||
input_free_device(input_dev);
|
||||
err1:
|
||||
kfree(tsc);
|
||||
@@ -357,7 +354,6 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
|
||||
struct input_dev *input_dev = tsc->input_dev;
|
||||
|
||||
cancel_delayed_work_sync(&tsc->work);
|
||||
destroy_workqueue(tsc->wq);
|
||||
|
||||
input_unregister_device(input_dev);
|
||||
|
||||
|
@@ -27,9 +27,6 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/tsc2007.h>
|
||||
|
||||
#define TS_POLL_DELAY 1 /* ms delay between samples */
|
||||
#define TS_POLL_PERIOD 1 /* ms delay between samples */
|
||||
|
||||
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
|
||||
#define TSC2007_MEASURE_AUX (0x2 << 4)
|
||||
#define TSC2007_MEASURE_TEMP1 (0x4 << 4)
|
||||
@@ -75,6 +72,9 @@ struct tsc2007 {
|
||||
|
||||
u16 model;
|
||||
u16 x_plate_ohms;
|
||||
u16 max_rt;
|
||||
unsigned long poll_delay;
|
||||
unsigned long poll_period;
|
||||
|
||||
bool pendown;
|
||||
int irq;
|
||||
@@ -156,6 +156,7 @@ static void tsc2007_work(struct work_struct *work)
|
||||
{
|
||||
struct tsc2007 *ts =
|
||||
container_of(to_delayed_work(work), struct tsc2007, work);
|
||||
bool debounced = false;
|
||||
struct ts_event tc;
|
||||
u32 rt;
|
||||
|
||||
@@ -184,13 +185,14 @@ static void tsc2007_work(struct work_struct *work)
|
||||
tsc2007_read_values(ts, &tc);
|
||||
|
||||
rt = tsc2007_calculate_pressure(ts, &tc);
|
||||
if (rt > MAX_12BIT) {
|
||||
if (rt > ts->max_rt) {
|
||||
/*
|
||||
* Sample found inconsistent by debouncing or pressure is
|
||||
* beyond the maximum. Don't report it to user space,
|
||||
* repeat at least once more the measurement.
|
||||
*/
|
||||
dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
|
||||
debounced = true;
|
||||
goto out;
|
||||
|
||||
}
|
||||
@@ -225,9 +227,9 @@ static void tsc2007_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
out:
|
||||
if (ts->pendown)
|
||||
if (ts->pendown || debounced)
|
||||
schedule_delayed_work(&ts->work,
|
||||
msecs_to_jiffies(TS_POLL_PERIOD));
|
||||
msecs_to_jiffies(ts->poll_period));
|
||||
else
|
||||
enable_irq(ts->irq);
|
||||
}
|
||||
@@ -239,7 +241,7 @@ static irqreturn_t tsc2007_irq(int irq, void *handle)
|
||||
if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
|
||||
disable_irq_nosync(ts->irq);
|
||||
schedule_delayed_work(&ts->work,
|
||||
msecs_to_jiffies(TS_POLL_DELAY));
|
||||
msecs_to_jiffies(ts->poll_delay));
|
||||
}
|
||||
|
||||
if (ts->clear_penirq)
|
||||
@@ -292,6 +294,9 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
|
||||
|
||||
ts->model = pdata->model;
|
||||
ts->x_plate_ohms = pdata->x_plate_ohms;
|
||||
ts->max_rt = pdata->max_rt ? : MAX_12BIT;
|
||||
ts->poll_delay = pdata->poll_delay ? : 1;
|
||||
ts->poll_period = pdata->poll_period ? : 1;
|
||||
ts->get_pendown_state = pdata->get_pendown_state;
|
||||
ts->clear_penirq = pdata->clear_penirq;
|
||||
|
||||
@@ -305,9 +310,10 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
|
||||
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
|
||||
pdata->fuzzz, 0);
|
||||
|
||||
if (pdata->init_platform_hw)
|
||||
pdata->init_platform_hw();
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* Spliting done by: Marek Vasut <marek.vasut@gmail.com>
|
||||
* If something doesnt work and it worked before spliting, e-mail me,
|
||||
* If something doesn't work and it worked before spliting, e-mail me,
|
||||
* dont bother Nicolas please ;-)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@@ -306,7 +306,7 @@ static int wm9705_acc_enable(struct wm97xx *wm, int enable)
|
||||
dig2 = wm->dig[2];
|
||||
|
||||
if (enable) {
|
||||
/* continous mode */
|
||||
/* continuous mode */
|
||||
if (wm->mach_ops->acc_startup &&
|
||||
(ret = wm->mach_ops->acc_startup(wm)) < 0)
|
||||
return ret;
|
||||
|
@@ -419,7 +419,7 @@ static int wm9712_acc_enable(struct wm97xx *wm, int enable)
|
||||
dig2 = wm->dig[2];
|
||||
|
||||
if (enable) {
|
||||
/* continous mode */
|
||||
/* continuous mode */
|
||||
if (wm->mach_ops->acc_startup) {
|
||||
ret = wm->mach_ops->acc_startup(wm);
|
||||
if (ret < 0)
|
||||
|
@@ -431,7 +431,7 @@ static int wm9713_acc_enable(struct wm97xx *wm, int enable)
|
||||
dig3 = wm->dig[2];
|
||||
|
||||
if (enable) {
|
||||
/* continous mode */
|
||||
/* continuous mode */
|
||||
if (wm->mach_ops->acc_startup &&
|
||||
(ret = wm->mach_ops->acc_startup(wm)) < 0)
|
||||
return ret;
|
||||
|
@@ -335,7 +335,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work)
|
||||
*/
|
||||
if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
|
||||
if (wm->pen_is_down && !pen_was_down) {
|
||||
/* Data is not availiable immediately on pen down */
|
||||
/* Data is not available immediately on pen down */
|
||||
queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work)
|
||||
* Codec PENDOWN irq handler
|
||||
*
|
||||
* We have to disable the codec interrupt in the handler because it
|
||||
* can take upto 1ms to clear the interrupt source. We schedule a task
|
||||
* can take up to 1ms to clear the interrupt source. We schedule a task
|
||||
* in a work queue to do the actual interaction with the chip. The
|
||||
* interrupt is then enabled again in the slow handler when the source
|
||||
* has been cleared.
|
||||
|
@@ -193,7 +193,7 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev)
|
||||
gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26);
|
||||
|
||||
wm->pen_irq = IRQ_GPIO(gpio_touch_irq);
|
||||
set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
|
||||
irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
|
||||
|
||||
wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
|
||||
WM97XX_GPIO_POL_HIGH,
|
||||
|
Reference in New Issue
Block a user