Skip to content

Commit 3b36fbb

Browse files
Roger Quadrosdtor
authored andcommitted
Input: pixcir_i2c_ts - initialize interrupt mode and power mode
Introduce helper functions to configure power and interrupt registers. Default to IDLE mode on probe as device supports auto wakeup to ACVIE mode on detecting finger touch. Configure interrupt mode and polarity on start up. Power down on device closure or module removal. Signed-off-by: Roger Quadros <rogerq@ti.com> Acked-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
1 parent e9d4718 commit 3b36fbb

2 files changed

Lines changed: 216 additions & 8 deletions

File tree

drivers/input/touchscreen/pixcir_i2c_ts.c

Lines changed: 174 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct pixcir_i2c_ts_data {
2929
struct i2c_client *client;
3030
struct input_dev *input;
3131
const struct pixcir_ts_platform_data *chip;
32-
bool exiting;
32+
bool running;
3333
};
3434

3535
static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
@@ -88,7 +88,7 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
8888
{
8989
struct pixcir_i2c_ts_data *tsdata = dev_id;
9090

91-
while (!tsdata->exiting) {
91+
while (tsdata->running) {
9292
pixcir_ts_poscheck(tsdata);
9393

9494
if (tsdata->chip->attb_read_val())
@@ -100,6 +100,164 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
100100
return IRQ_HANDLED;
101101
}
102102

103+
static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
104+
enum pixcir_power_mode mode)
105+
{
106+
struct device *dev = &ts->client->dev;
107+
int ret;
108+
109+
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
110+
if (ret < 0) {
111+
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
112+
__func__, PIXCIR_REG_POWER_MODE, ret);
113+
return ret;
114+
}
115+
116+
ret &= ~PIXCIR_POWER_MODE_MASK;
117+
ret |= mode;
118+
119+
/* Always AUTO_IDLE */
120+
ret |= PIXCIR_POWER_ALLOW_IDLE;
121+
122+
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
123+
if (ret < 0) {
124+
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
125+
__func__, PIXCIR_REG_POWER_MODE, ret);
126+
return ret;
127+
}
128+
129+
return 0;
130+
}
131+
132+
/*
133+
* Set the interrupt mode for the device i.e. ATTB line behaviour
134+
*
135+
* @polarity : 1 for active high, 0 for active low.
136+
*/
137+
static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
138+
enum pixcir_int_mode mode, bool polarity)
139+
{
140+
struct device *dev = &ts->client->dev;
141+
int ret;
142+
143+
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
144+
if (ret < 0) {
145+
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
146+
__func__, PIXCIR_REG_INT_MODE, ret);
147+
return ret;
148+
}
149+
150+
ret &= ~PIXCIR_INT_MODE_MASK;
151+
ret |= mode;
152+
153+
if (polarity)
154+
ret |= PIXCIR_INT_POL_HIGH;
155+
else
156+
ret &= ~PIXCIR_INT_POL_HIGH;
157+
158+
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
159+
if (ret < 0) {
160+
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
161+
__func__, PIXCIR_REG_INT_MODE, ret);
162+
return ret;
163+
}
164+
165+
return 0;
166+
}
167+
168+
/*
169+
* Enable/disable interrupt generation
170+
*/
171+
static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
172+
{
173+
struct device *dev = &ts->client->dev;
174+
int ret;
175+
176+
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
177+
if (ret < 0) {
178+
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
179+
__func__, PIXCIR_REG_INT_MODE, ret);
180+
return ret;
181+
}
182+
183+
if (enable)
184+
ret |= PIXCIR_INT_ENABLE;
185+
else
186+
ret &= ~PIXCIR_INT_ENABLE;
187+
188+
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
189+
if (ret < 0) {
190+
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
191+
__func__, PIXCIR_REG_INT_MODE, ret);
192+
return ret;
193+
}
194+
195+
return 0;
196+
}
197+
198+
static int pixcir_start(struct pixcir_i2c_ts_data *ts)
199+
{
200+
struct device *dev = &ts->client->dev;
201+
int error;
202+
203+
/* LEVEL_TOUCH interrupt with active low polarity */
204+
error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
205+
if (error) {
206+
dev_err(dev, "Failed to set interrupt mode: %d\n", error);
207+
return error;
208+
}
209+
210+
ts->running = true;
211+
mb(); /* Update status before IRQ can fire */
212+
213+
/* enable interrupt generation */
214+
error = pixcir_int_enable(ts, true);
215+
if (error) {
216+
dev_err(dev, "Failed to enable interrupt generation: %d\n",
217+
error);
218+
return error;
219+
}
220+
221+
return 0;
222+
}
223+
224+
static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
225+
{
226+
int error;
227+
228+
/* Disable interrupt generation */
229+
error = pixcir_int_enable(ts, false);
230+
if (error) {
231+
dev_err(&ts->client->dev,
232+
"Failed to disable interrupt generation: %d\n",
233+
error);
234+
return error;
235+
}
236+
237+
/* Exit ISR if running, no more report parsing */
238+
ts->running = false;
239+
mb(); /* update status before we synchronize irq */
240+
241+
/* Wait till running ISR is complete */
242+
synchronize_irq(ts->client->irq);
243+
244+
return 0;
245+
}
246+
247+
static int pixcir_input_open(struct input_dev *dev)
248+
{
249+
struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
250+
251+
return pixcir_start(ts);
252+
}
253+
254+
static void pixcir_input_close(struct input_dev *dev)
255+
{
256+
struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
257+
258+
pixcir_stop(ts);
259+
}
260+
103261
#ifdef CONFIG_PM_SLEEP
104262
static int pixcir_i2c_ts_suspend(struct device *dev)
105263
{
@@ -156,6 +314,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
156314

157315
input->name = client->name;
158316
input->id.bustype = BUS_I2C;
317+
input->open = pixcir_input_open;
318+
input->close = pixcir_input_close;
159319
input->dev.parent = &client->dev;
160320

161321
__set_bit(EV_KEY, input->evbit);
@@ -176,25 +336,31 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
176336
return error;
177337
}
178338

339+
/* Always be in IDLE mode to save power, device supports auto wake */
340+
error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
341+
if (error) {
342+
dev_err(dev, "Failed to set IDLE mode\n");
343+
return error;
344+
}
345+
346+
/* Stop device till opened */
347+
error = pixcir_stop(tsdata);
348+
if (error)
349+
return error;
350+
179351
error = input_register_device(input);
180352
if (error)
181353
return error;
182354

183-
i2c_set_clientdata(client, tsdata);
184355
device_init_wakeup(&client->dev, 1);
185356

186357
return 0;
187358
}
188359

189360
static int pixcir_i2c_ts_remove(struct i2c_client *client)
190361
{
191-
struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
192-
193362
device_init_wakeup(&client->dev, 0);
194363

195-
tsdata->exiting = true;
196-
mb();
197-
198364
return 0;
199365
}
200366

include/linux/input/pixcir_ts.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
11
#ifndef _PIXCIR_I2C_TS_H
22
#define _PIXCIR_I2C_TS_H
33

4+
/*
5+
* Register map
6+
*/
7+
#define PIXCIR_REG_POWER_MODE 51
8+
#define PIXCIR_REG_INT_MODE 52
9+
10+
/*
11+
* Power modes:
12+
* active: max scan speed
13+
* idle: lower scan speed with automatic transition to active on touch
14+
* halt: datasheet says sleep but this is more like halt as the chip
15+
* clocks are cut and it can only be brought out of this mode
16+
* using the RESET pin.
17+
*/
18+
enum pixcir_power_mode {
19+
PIXCIR_POWER_ACTIVE,
20+
PIXCIR_POWER_IDLE,
21+
PIXCIR_POWER_HALT,
22+
};
23+
24+
#define PIXCIR_POWER_MODE_MASK 0x03
25+
#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
26+
27+
/*
28+
* Interrupt modes:
29+
* periodical: interrupt is asserted periodicaly
30+
* diff coordinates: interrupt is asserted when coordinates change
31+
* level on touch: interrupt level asserted during touch
32+
* pulse on touch: interrupt pulse asserted druing touch
33+
*
34+
*/
35+
enum pixcir_int_mode {
36+
PIXCIR_INT_PERIODICAL,
37+
PIXCIR_INT_DIFF_COORD,
38+
PIXCIR_INT_LEVEL_TOUCH,
39+
PIXCIR_INT_PULSE_TOUCH,
40+
};
41+
42+
#define PIXCIR_INT_MODE_MASK 0x03
43+
#define PIXCIR_INT_ENABLE (1UL << 3)
44+
#define PIXCIR_INT_POL_HIGH (1UL << 2)
45+
446
struct pixcir_ts_platform_data {
547
int (*attb_read_val)(void);
648
int x_max;

0 commit comments

Comments
 (0)