aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/touchscreen/wm831x-ts.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
index 6ae054f8e0aa..b9373012b3e6 100644
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -68,8 +68,23 @@ struct wm831x_ts {
68 unsigned int pd_irq; 68 unsigned int pd_irq;
69 bool pressure; 69 bool pressure;
70 bool pen_down; 70 bool pen_down;
71 struct work_struct pd_data_work;
71}; 72};
72 73
74static void wm831x_pd_data_work(struct work_struct *work)
75{
76 struct wm831x_ts *wm831x_ts =
77 container_of(work, struct wm831x_ts, pd_data_work);
78
79 if (wm831x_ts->pen_down) {
80 enable_irq(wm831x_ts->data_irq);
81 dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
82 } else {
83 enable_irq(wm831x_ts->pd_irq);
84 dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
85 }
86}
87
73static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) 88static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
74{ 89{
75 struct wm831x_ts *wm831x_ts = irq_data; 90 struct wm831x_ts *wm831x_ts = irq_data;
@@ -110,6 +125,9 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
110 } 125 }
111 126
112 if (!wm831x_ts->pen_down) { 127 if (!wm831x_ts->pen_down) {
128 /* Switch from data to pen down */
129 dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
130
113 disable_irq_nosync(wm831x_ts->data_irq); 131 disable_irq_nosync(wm831x_ts->data_irq);
114 132
115 /* Don't need data any more */ 133 /* Don't need data any more */
@@ -128,6 +146,8 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
128 ABS_PRESSURE, 0); 146 ABS_PRESSURE, 0);
129 147
130 input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); 148 input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
149
150 schedule_work(&wm831x_ts->pd_data_work);
131 } 151 }
132 152
133 input_sync(wm831x_ts->input_dev); 153 input_sync(wm831x_ts->input_dev);
@@ -141,6 +161,11 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
141 struct wm831x *wm831x = wm831x_ts->wm831x; 161 struct wm831x *wm831x = wm831x_ts->wm831x;
142 int ena = 0; 162 int ena = 0;
143 163
164 if (wm831x_ts->pen_down)
165 return IRQ_HANDLED;
166
167 disable_irq_nosync(wm831x_ts->pd_irq);
168
144 /* Start collecting data */ 169 /* Start collecting data */
145 if (wm831x_ts->pressure) 170 if (wm831x_ts->pressure)
146 ena |= WM831X_TCH_Z_ENA; 171 ena |= WM831X_TCH_Z_ENA;
@@ -156,7 +181,10 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
156 WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); 181 WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
157 182
158 wm831x_ts->pen_down = true; 183 wm831x_ts->pen_down = true;
159 enable_irq(wm831x_ts->data_irq); 184
185 /* Switch from pen down to data */
186 dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
187 schedule_work(&wm831x_ts->pd_data_work);
160 188
161 return IRQ_HANDLED; 189 return IRQ_HANDLED;
162} 190}
@@ -182,13 +210,28 @@ static void wm831x_ts_input_close(struct input_dev *idev)
182 struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); 210 struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
183 struct wm831x *wm831x = wm831x_ts->wm831x; 211 struct wm831x *wm831x = wm831x_ts->wm831x;
184 212
213 /* Shut the controller down, disabling all other functionality too */
185 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, 214 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
186 WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | 215 WM831X_TCH_ENA | WM831X_TCH_X_ENA |
187 WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | 216 WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
188 WM831X_TCH_Z_ENA, 0);
189 217
190 if (wm831x_ts->pen_down) 218 /* Make sure any pending IRQs are done, the above will prevent
219 * new ones firing.
220 */
221 synchronize_irq(wm831x_ts->data_irq);
222 synchronize_irq(wm831x_ts->pd_irq);
223
224 /* Make sure the IRQ completion work is quiesced */
225 flush_work_sync(&wm831x_ts->pd_data_work);
226
227 /* If we ended up with the pen down then make sure we revert back
228 * to pen detection state for the next time we start up.
229 */
230 if (wm831x_ts->pen_down) {
191 disable_irq(wm831x_ts->data_irq); 231 disable_irq(wm831x_ts->data_irq);
232 enable_irq(wm831x_ts->pd_irq);
233 wm831x_ts->pen_down = false;
234 }
192} 235}
193 236
194static __devinit int wm831x_ts_probe(struct platform_device *pdev) 237static __devinit int wm831x_ts_probe(struct platform_device *pdev)
@@ -212,6 +255,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
212 255
213 wm831x_ts->wm831x = wm831x; 256 wm831x_ts->wm831x = wm831x;
214 wm831x_ts->input_dev = input_dev; 257 wm831x_ts->input_dev = input_dev;
258 INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
215 259
216 /* 260 /*
217 * If we have a direct IRQ use it, otherwise use the interrupt 261 * If we have a direct IRQ use it, otherwise use the interrupt