aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/pixcir_i2c_ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/pixcir_i2c_ts.c')
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c182
1 files changed, 174 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 5d36243bdc79..6c6f6dacb858 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -29,7 +29,7 @@ struct pixcir_i2c_ts_data {
29 struct i2c_client *client; 29 struct i2c_client *client;
30 struct input_dev *input; 30 struct input_dev *input;
31 const struct pixcir_ts_platform_data *chip; 31 const struct pixcir_ts_platform_data *chip;
32 bool exiting; 32 bool running;
33}; 33};
34 34
35static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) 35static 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)
88{ 88{
89 struct pixcir_i2c_ts_data *tsdata = dev_id; 89 struct pixcir_i2c_ts_data *tsdata = dev_id;
90 90
91 while (!tsdata->exiting) { 91 while (tsdata->running) {
92 pixcir_ts_poscheck(tsdata); 92 pixcir_ts_poscheck(tsdata);
93 93
94 if (tsdata->chip->attb_read_val()) 94 if (tsdata->chip->attb_read_val())
@@ -100,6 +100,164 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
100 return IRQ_HANDLED; 100 return IRQ_HANDLED;
101} 101}
102 102
103static 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 */
137static 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 */
171static 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
198static 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
224static 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
247static 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
254static 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
103#ifdef CONFIG_PM_SLEEP 261#ifdef CONFIG_PM_SLEEP
104static int pixcir_i2c_ts_suspend(struct device *dev) 262static int pixcir_i2c_ts_suspend(struct device *dev)
105{ 263{
@@ -156,6 +314,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
156 314
157 input->name = client->name; 315 input->name = client->name;
158 input->id.bustype = BUS_I2C; 316 input->id.bustype = BUS_I2C;
317 input->open = pixcir_input_open;
318 input->close = pixcir_input_close;
159 input->dev.parent = &client->dev; 319 input->dev.parent = &client->dev;
160 320
161 __set_bit(EV_KEY, input->evbit); 321 __set_bit(EV_KEY, input->evbit);
@@ -176,11 +336,22 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
176 return error; 336 return error;
177 } 337 }
178 338
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
179 error = input_register_device(input); 351 error = input_register_device(input);
180 if (error) 352 if (error)
181 return error; 353 return error;
182 354
183 i2c_set_clientdata(client, tsdata);
184 device_init_wakeup(&client->dev, 1); 355 device_init_wakeup(&client->dev, 1);
185 356
186 return 0; 357 return 0;
@@ -188,13 +359,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
188 359
189static int pixcir_i2c_ts_remove(struct i2c_client *client) 360static int pixcir_i2c_ts_remove(struct i2c_client *client)
190{ 361{
191 struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
192
193 device_init_wakeup(&client->dev, 0); 362 device_init_wakeup(&client->dev, 0);
194 363
195 tsdata->exiting = true;
196 mb();
197
198 return 0; 364 return 0;
199} 365}
200 366