Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: wm831x-ts - move BTN_TOUCH reporting to data transfer
Input: wm831x-ts - allow IRQ flags to be specified
Input: wm831x-ts - fix races with IRQ management

+66 -11
+64 -11
drivers/input/touchscreen/wm831x-ts.c
··· 68 68 unsigned int pd_irq; 69 69 bool pressure; 70 70 bool pen_down; 71 + struct work_struct pd_data_work; 71 72 }; 73 + 74 + static 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 + } 72 87 73 88 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) 74 89 { ··· 125 110 } 126 111 127 112 if (!wm831x_ts->pen_down) { 113 + /* Switch from data to pen down */ 114 + dev_dbg(wm831x->dev, "IRQ DATA->PD\n"); 115 + 128 116 disable_irq_nosync(wm831x_ts->data_irq); 129 117 130 118 /* Don't need data any more */ ··· 146 128 ABS_PRESSURE, 0); 147 129 148 130 input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); 131 + 132 + schedule_work(&wm831x_ts->pd_data_work); 133 + } else { 134 + input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1); 149 135 } 150 136 151 137 input_sync(wm831x_ts->input_dev); ··· 163 141 struct wm831x *wm831x = wm831x_ts->wm831x; 164 142 int ena = 0; 165 143 144 + if (wm831x_ts->pen_down) 145 + return IRQ_HANDLED; 146 + 147 + disable_irq_nosync(wm831x_ts->pd_irq); 148 + 166 149 /* Start collecting data */ 167 150 if (wm831x_ts->pressure) 168 151 ena |= WM831X_TCH_Z_ENA; ··· 176 149 WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 177 150 WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena); 178 151 179 - input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1); 180 - input_sync(wm831x_ts->input_dev); 181 - 182 152 wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1, 183 153 WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); 184 154 185 155 wm831x_ts->pen_down = true; 186 - enable_irq(wm831x_ts->data_irq); 156 + 157 + /* Switch from pen down to data */ 158 + dev_dbg(wm831x->dev, "IRQ PD->DATA\n"); 159 + schedule_work(&wm831x_ts->pd_data_work); 187 160 188 161 return IRQ_HANDLED; 189 162 } ··· 209 182 struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); 210 183 struct wm831x *wm831x = wm831x_ts->wm831x; 211 184 185 + /* Shut the controller down, disabling all other functionality too */ 212 186 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, 213 - WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | 214 - WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | 215 - WM831X_TCH_Z_ENA, 0); 187 + WM831X_TCH_ENA | WM831X_TCH_X_ENA | 188 + WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0); 216 189 217 - if (wm831x_ts->pen_down) 190 + /* Make sure any pending IRQs are done, the above will prevent 191 + * new ones firing. 192 + */ 193 + synchronize_irq(wm831x_ts->data_irq); 194 + synchronize_irq(wm831x_ts->pd_irq); 195 + 196 + /* Make sure the IRQ completion work is quiesced */ 197 + flush_work_sync(&wm831x_ts->pd_data_work); 198 + 199 + /* If we ended up with the pen down then make sure we revert back 200 + * to pen detection state for the next time we start up. 201 + */ 202 + if (wm831x_ts->pen_down) { 218 203 disable_irq(wm831x_ts->data_irq); 204 + enable_irq(wm831x_ts->pd_irq); 205 + wm831x_ts->pen_down = false; 206 + } 219 207 } 220 208 221 209 static __devinit int wm831x_ts_probe(struct platform_device *pdev) ··· 240 198 struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent); 241 199 struct wm831x_touch_pdata *pdata = NULL; 242 200 struct input_dev *input_dev; 243 - int error; 201 + int error, irqf; 244 202 245 203 if (core_pdata) 246 204 pdata = core_pdata->touch; ··· 254 212 255 213 wm831x_ts->wm831x = wm831x; 256 214 wm831x_ts->input_dev = input_dev; 215 + INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work); 257 216 258 217 /* 259 218 * If we have a direct IRQ use it, otherwise use the interrupt ··· 313 270 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, 314 271 WM831X_TCH_RATE_MASK, 6); 315 272 273 + if (pdata && pdata->data_irqf) 274 + irqf = pdata->data_irqf; 275 + else 276 + irqf = IRQF_TRIGGER_HIGH; 277 + 316 278 error = request_threaded_irq(wm831x_ts->data_irq, 317 279 NULL, wm831x_ts_data_irq, 318 - IRQF_ONESHOT, 280 + irqf | IRQF_ONESHOT, 319 281 "Touchscreen data", wm831x_ts); 320 282 if (error) { 321 283 dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n", ··· 329 281 } 330 282 disable_irq(wm831x_ts->data_irq); 331 283 284 + if (pdata && pdata->pd_irqf) 285 + irqf = pdata->pd_irqf; 286 + else 287 + irqf = IRQF_TRIGGER_HIGH; 288 + 332 289 error = request_threaded_irq(wm831x_ts->pd_irq, 333 290 NULL, wm831x_ts_pen_down_irq, 334 - IRQF_ONESHOT, 291 + irqf | IRQF_ONESHOT, 335 292 "Touchscreen pen down", wm831x_ts); 336 293 if (error) { 337 294 dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
+2
include/linux/mfd/wm831x/pdata.h
··· 81 81 int rpu; /** Pen down sensitivity resistor divider */ 82 82 int pressure; /** Report pressure (boolean) */ 83 83 unsigned int data_irq; /** Touch data ready IRQ */ 84 + int data_irqf; /** IRQ flags for data ready IRQ */ 84 85 unsigned int pd_irq; /** Touch pendown detect IRQ */ 86 + int pd_irqf; /** IRQ flags for pen down IRQ */ 85 87 }; 86 88 87 89 enum wm831x_watchdog_action {