|
@@ -27,70 +27,10 @@
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c/tsc2007.h>
|
|
#include <linux/i2c/tsc2007.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_device.h>
|
|
-#include <linux/of.h>
|
|
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/of_gpio.h>
|
|
|
|
+#include "tsc2007.h"
|
|
|
|
|
|
-#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
|
|
|
|
-#define TSC2007_MEASURE_AUX (0x2 << 4)
|
|
|
|
-#define TSC2007_MEASURE_TEMP1 (0x4 << 4)
|
|
|
|
-#define TSC2007_ACTIVATE_XN (0x8 << 4)
|
|
|
|
-#define TSC2007_ACTIVATE_YN (0x9 << 4)
|
|
|
|
-#define TSC2007_ACTIVATE_YP_XN (0xa << 4)
|
|
|
|
-#define TSC2007_SETUP (0xb << 4)
|
|
|
|
-#define TSC2007_MEASURE_X (0xc << 4)
|
|
|
|
-#define TSC2007_MEASURE_Y (0xd << 4)
|
|
|
|
-#define TSC2007_MEASURE_Z1 (0xe << 4)
|
|
|
|
-#define TSC2007_MEASURE_Z2 (0xf << 4)
|
|
|
|
-
|
|
|
|
-#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2)
|
|
|
|
-#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2)
|
|
|
|
-#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2)
|
|
|
|
-#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2)
|
|
|
|
-
|
|
|
|
-#define TSC2007_12BIT (0x0 << 1)
|
|
|
|
-#define TSC2007_8BIT (0x1 << 1)
|
|
|
|
-
|
|
|
|
-#define MAX_12BIT ((1 << 12) - 1)
|
|
|
|
-
|
|
|
|
-#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0)
|
|
|
|
-
|
|
|
|
-#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y)
|
|
|
|
-#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1)
|
|
|
|
-#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2)
|
|
|
|
-#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X)
|
|
|
|
-#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
|
|
|
|
-
|
|
|
|
-struct ts_event {
|
|
|
|
- u16 x;
|
|
|
|
- u16 y;
|
|
|
|
- u16 z1, z2;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-struct tsc2007 {
|
|
|
|
- struct input_dev *input;
|
|
|
|
- char phys[32];
|
|
|
|
-
|
|
|
|
- struct i2c_client *client;
|
|
|
|
-
|
|
|
|
- u16 model;
|
|
|
|
- u16 x_plate_ohms;
|
|
|
|
- u16 max_rt;
|
|
|
|
- unsigned long poll_period; /* in jiffies */
|
|
|
|
- int fuzzx;
|
|
|
|
- int fuzzy;
|
|
|
|
- int fuzzz;
|
|
|
|
-
|
|
|
|
- unsigned gpio;
|
|
|
|
- int irq;
|
|
|
|
-
|
|
|
|
- wait_queue_head_t wait;
|
|
|
|
- bool stopped;
|
|
|
|
-
|
|
|
|
- int (*get_pendown_state)(struct device *);
|
|
|
|
- void (*clear_penirq)(void);
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
|
|
|
|
|
|
+int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
|
|
{
|
|
{
|
|
s32 data;
|
|
s32 data;
|
|
u16 val;
|
|
u16 val;
|
|
@@ -128,7 +68,7 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
|
|
tsc2007_xfer(tsc, PWRDOWN);
|
|
tsc2007_xfer(tsc, PWRDOWN);
|
|
}
|
|
}
|
|
|
|
|
|
-static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
|
|
|
|
|
|
+u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
|
|
{
|
|
{
|
|
u32 rt = 0;
|
|
u32 rt = 0;
|
|
|
|
|
|
@@ -137,7 +77,7 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
|
|
tc->x = 0;
|
|
tc->x = 0;
|
|
|
|
|
|
if (likely(tc->x && tc->z1)) {
|
|
if (likely(tc->x && tc->z1)) {
|
|
- /* compute touch pressure resistance using equation #1 */
|
|
|
|
|
|
+ /* compute touch resistance using equation #1 */
|
|
rt = tc->z2 - tc->z1;
|
|
rt = tc->z2 - tc->z1;
|
|
rt *= tc->x;
|
|
rt *= tc->x;
|
|
rt *= tsc->x_plate_ohms;
|
|
rt *= tsc->x_plate_ohms;
|
|
@@ -148,7 +88,7 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
|
|
return rt;
|
|
return rt;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool tsc2007_is_pen_down(struct tsc2007 *ts)
|
|
|
|
|
|
+bool tsc2007_is_pen_down(struct tsc2007 *ts)
|
|
{
|
|
{
|
|
/*
|
|
/*
|
|
* NOTE: We can't rely on the pressure to determine the pen down
|
|
* NOTE: We can't rely on the pressure to determine the pen down
|
|
@@ -180,9 +120,12 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
|
|
while (!ts->stopped && tsc2007_is_pen_down(ts)) {
|
|
while (!ts->stopped && tsc2007_is_pen_down(ts)) {
|
|
|
|
|
|
/* pen is down, continue with the measurement */
|
|
/* pen is down, continue with the measurement */
|
|
|
|
+
|
|
|
|
+ mutex_lock(&ts->mlock);
|
|
tsc2007_read_values(ts, &tc);
|
|
tsc2007_read_values(ts, &tc);
|
|
|
|
+ mutex_unlock(&ts->mlock);
|
|
|
|
|
|
- rt = tsc2007_calculate_pressure(ts, &tc);
|
|
|
|
|
|
+ rt = tsc2007_calculate_resistance(ts, &tc);
|
|
|
|
|
|
if (!rt && !ts->get_pendown_state) {
|
|
if (!rt && !ts->get_pendown_state) {
|
|
/*
|
|
/*
|
|
@@ -195,9 +138,11 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
|
|
|
|
|
|
if (rt <= ts->max_rt) {
|
|
if (rt <= ts->max_rt) {
|
|
dev_dbg(&ts->client->dev,
|
|
dev_dbg(&ts->client->dev,
|
|
- "DOWN point(%4d,%4d), pressure (%4u)\n",
|
|
|
|
|
|
+ "DOWN point(%4d,%4d), resistance (%4u)\n",
|
|
tc.x, tc.y, rt);
|
|
tc.x, tc.y, rt);
|
|
|
|
|
|
|
|
+ rt = ts->max_rt - rt;
|
|
|
|
+
|
|
input_report_key(input, BTN_TOUCH, 1);
|
|
input_report_key(input, BTN_TOUCH, 1);
|
|
input_report_abs(input, ABS_X, tc.x);
|
|
input_report_abs(input, ABS_X, tc.x);
|
|
input_report_abs(input, ABS_Y, tc.y);
|
|
input_report_abs(input, ABS_Y, tc.y);
|
|
@@ -375,7 +320,8 @@ static void tsc2007_call_exit_platform_hw(void *data)
|
|
static int tsc2007_probe(struct i2c_client *client,
|
|
static int tsc2007_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *id)
|
|
const struct i2c_device_id *id)
|
|
{
|
|
{
|
|
- const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev);
|
|
|
|
|
|
+ const struct tsc2007_platform_data *pdata =
|
|
|
|
+ dev_get_platdata(&client->dev);
|
|
struct tsc2007 *ts;
|
|
struct tsc2007 *ts;
|
|
struct input_dev *input_dev;
|
|
struct input_dev *input_dev;
|
|
int err;
|
|
int err;
|
|
@@ -404,7 +350,9 @@ static int tsc2007_probe(struct i2c_client *client,
|
|
ts->client = client;
|
|
ts->client = client;
|
|
ts->irq = client->irq;
|
|
ts->irq = client->irq;
|
|
ts->input = input_dev;
|
|
ts->input = input_dev;
|
|
|
|
+
|
|
init_waitqueue_head(&ts->wait);
|
|
init_waitqueue_head(&ts->wait);
|
|
|
|
+ mutex_init(&ts->mlock);
|
|
|
|
|
|
snprintf(ts->phys, sizeof(ts->phys),
|
|
snprintf(ts->phys, sizeof(ts->phys),
|
|
"%s/input0", dev_name(&client->dev));
|
|
"%s/input0", dev_name(&client->dev));
|
|
@@ -418,8 +366,7 @@ static int tsc2007_probe(struct i2c_client *client,
|
|
|
|
|
|
input_set_drvdata(input_dev, ts);
|
|
input_set_drvdata(input_dev, ts);
|
|
|
|
|
|
- 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_capability(input_dev, EV_KEY, BTN_TOUCH);
|
|
|
|
|
|
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
|
|
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
|
|
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
|
|
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
|
|
@@ -455,6 +402,14 @@ static int tsc2007_probe(struct i2c_client *client,
|
|
|
|
|
|
tsc2007_stop(ts);
|
|
tsc2007_stop(ts);
|
|
|
|
|
|
|
|
+ /* power down the chip (TSC2007_SETUP does not ACK on I2C) */
|
|
|
|
+ err = tsc2007_xfer(ts, PWRDOWN);
|
|
|
|
+ if (err < 0) {
|
|
|
|
+ dev_err(&client->dev,
|
|
|
|
+ "Failed to setup chip: %d\n", err);
|
|
|
|
+ return err; /* chip does not respond */
|
|
|
|
+ }
|
|
|
|
+
|
|
err = input_register_device(input_dev);
|
|
err = input_register_device(input_dev);
|
|
if (err) {
|
|
if (err) {
|
|
dev_err(&client->dev,
|
|
dev_err(&client->dev,
|
|
@@ -462,6 +417,13 @@ static int tsc2007_probe(struct i2c_client *client,
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ err = tsc2007_iio_configure(ts);
|
|
|
|
+ if (err) {
|
|
|
|
+ dev_err(&client->dev,
|
|
|
|
+ "Failed to register with IIO: %d\n", err);
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|