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
This commit is contained in:
commit
497ff03444
2 changed files with 66 additions and 11 deletions
|
@ -68,8 +68,23 @@ struct wm831x_ts {
|
|||
unsigned int pd_irq;
|
||||
bool pressure;
|
||||
bool pen_down;
|
||||
struct work_struct pd_data_work;
|
||||
};
|
||||
|
||||
static void wm831x_pd_data_work(struct work_struct *work)
|
||||
{
|
||||
struct wm831x_ts *wm831x_ts =
|
||||
container_of(work, struct wm831x_ts, pd_data_work);
|
||||
|
||||
if (wm831x_ts->pen_down) {
|
||||
enable_irq(wm831x_ts->data_irq);
|
||||
dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
|
||||
} else {
|
||||
enable_irq(wm831x_ts->pd_irq);
|
||||
dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
|
||||
{
|
||||
struct wm831x_ts *wm831x_ts = irq_data;
|
||||
|
@ -110,6 +125,9 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
|
|||
}
|
||||
|
||||
if (!wm831x_ts->pen_down) {
|
||||
/* Switch from data to pen down */
|
||||
dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
|
||||
|
||||
disable_irq_nosync(wm831x_ts->data_irq);
|
||||
|
||||
/* Don't need data any more */
|
||||
|
@ -128,6 +146,10 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
|
|||
ABS_PRESSURE, 0);
|
||||
|
||||
input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
|
||||
|
||||
schedule_work(&wm831x_ts->pd_data_work);
|
||||
} else {
|
||||
input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
|
||||
}
|
||||
|
||||
input_sync(wm831x_ts->input_dev);
|
||||
|
@ -141,6 +163,11 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
|
|||
struct wm831x *wm831x = wm831x_ts->wm831x;
|
||||
int ena = 0;
|
||||
|
||||
if (wm831x_ts->pen_down)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
disable_irq_nosync(wm831x_ts->pd_irq);
|
||||
|
||||
/* Start collecting data */
|
||||
if (wm831x_ts->pressure)
|
||||
ena |= WM831X_TCH_Z_ENA;
|
||||
|
@ -149,14 +176,14 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
|
|||
WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
|
||||
WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
|
||||
|
||||
input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
|
||||
input_sync(wm831x_ts->input_dev);
|
||||
|
||||
wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
|
||||
WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
|
||||
|
||||
wm831x_ts->pen_down = true;
|
||||
enable_irq(wm831x_ts->data_irq);
|
||||
|
||||
/* Switch from pen down to data */
|
||||
dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
|
||||
schedule_work(&wm831x_ts->pd_data_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -182,13 +209,28 @@ static void wm831x_ts_input_close(struct input_dev *idev)
|
|||
struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
|
||||
struct wm831x *wm831x = wm831x_ts->wm831x;
|
||||
|
||||
/* Shut the controller down, disabling all other functionality too */
|
||||
wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
|
||||
WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
|
||||
WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
|
||||
WM831X_TCH_Z_ENA, 0);
|
||||
WM831X_TCH_ENA | WM831X_TCH_X_ENA |
|
||||
WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
|
||||
|
||||
if (wm831x_ts->pen_down)
|
||||
/* Make sure any pending IRQs are done, the above will prevent
|
||||
* new ones firing.
|
||||
*/
|
||||
synchronize_irq(wm831x_ts->data_irq);
|
||||
synchronize_irq(wm831x_ts->pd_irq);
|
||||
|
||||
/* Make sure the IRQ completion work is quiesced */
|
||||
flush_work_sync(&wm831x_ts->pd_data_work);
|
||||
|
||||
/* If we ended up with the pen down then make sure we revert back
|
||||
* to pen detection state for the next time we start up.
|
||||
*/
|
||||
if (wm831x_ts->pen_down) {
|
||||
disable_irq(wm831x_ts->data_irq);
|
||||
enable_irq(wm831x_ts->pd_irq);
|
||||
wm831x_ts->pen_down = false;
|
||||
}
|
||||
}
|
||||
|
||||
static __devinit int wm831x_ts_probe(struct platform_device *pdev)
|
||||
|
@ -198,7 +240,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
|
|||
struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
|
||||
struct wm831x_touch_pdata *pdata = NULL;
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
int error, irqf;
|
||||
|
||||
if (core_pdata)
|
||||
pdata = core_pdata->touch;
|
||||
|
@ -212,6 +254,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
|
|||
|
||||
wm831x_ts->wm831x = wm831x;
|
||||
wm831x_ts->input_dev = input_dev;
|
||||
INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
|
||||
|
||||
/*
|
||||
* If we have a direct IRQ use it, otherwise use the interrupt
|
||||
|
@ -270,9 +313,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
|
|||
wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
|
||||
WM831X_TCH_RATE_MASK, 6);
|
||||
|
||||
if (pdata && pdata->data_irqf)
|
||||
irqf = pdata->data_irqf;
|
||||
else
|
||||
irqf = IRQF_TRIGGER_HIGH;
|
||||
|
||||
error = request_threaded_irq(wm831x_ts->data_irq,
|
||||
NULL, wm831x_ts_data_irq,
|
||||
IRQF_ONESHOT,
|
||||
irqf | IRQF_ONESHOT,
|
||||
"Touchscreen data", wm831x_ts);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
|
||||
|
@ -281,9 +329,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
|
|||
}
|
||||
disable_irq(wm831x_ts->data_irq);
|
||||
|
||||
if (pdata && pdata->pd_irqf)
|
||||
irqf = pdata->pd_irqf;
|
||||
else
|
||||
irqf = IRQF_TRIGGER_HIGH;
|
||||
|
||||
error = request_threaded_irq(wm831x_ts->pd_irq,
|
||||
NULL, wm831x_ts_pen_down_irq,
|
||||
IRQF_ONESHOT,
|
||||
irqf | IRQF_ONESHOT,
|
||||
"Touchscreen pen down", wm831x_ts);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
|
||||
|
|
|
@ -81,7 +81,9 @@ struct wm831x_touch_pdata {
|
|||
int rpu; /** Pen down sensitivity resistor divider */
|
||||
int pressure; /** Report pressure (boolean) */
|
||||
unsigned int data_irq; /** Touch data ready IRQ */
|
||||
int data_irqf; /** IRQ flags for data ready IRQ */
|
||||
unsigned int pd_irq; /** Touch pendown detect IRQ */
|
||||
int pd_irqf; /** IRQ flags for pen down IRQ */
|
||||
};
|
||||
|
||||
enum wm831x_watchdog_action {
|
||||
|
|
Loading…
Reference in a new issue