Input: migor-ts - convert to a threaded IRQ
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Родитель
e23ed600ba
Коммит
468792eb1e
|
@ -36,7 +36,6 @@
|
|||
struct migor_ts_priv {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
struct delayed_work work;
|
||||
int irq;
|
||||
};
|
||||
|
||||
|
@ -44,15 +43,24 @@ static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11,
|
|||
0x01, 0x06, 0x07, };
|
||||
static const u_int8_t migor_ts_dis_seq[17] = { };
|
||||
|
||||
static void migor_ts_poscheck(struct work_struct *work)
|
||||
static irqreturn_t migor_ts_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct migor_ts_priv *priv = container_of(work,
|
||||
struct migor_ts_priv,
|
||||
work.work);
|
||||
struct migor_ts_priv *priv = dev_id;
|
||||
unsigned short xpos, ypos;
|
||||
unsigned char event;
|
||||
u_int8_t buf[16];
|
||||
|
||||
/*
|
||||
* The touch screen controller chip is hooked up to the CPU
|
||||
* using I2C and a single interrupt line. The interrupt line
|
||||
* is pulled low whenever someone taps the screen. To deassert
|
||||
* the interrupt line we need to acknowledge the interrupt by
|
||||
* communicating with the controller over the slow i2c bus.
|
||||
*
|
||||
* Since I2C bus controller may sleep we are using threaded
|
||||
* IRQ here.
|
||||
*/
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* Set Index 0 */
|
||||
|
@ -72,41 +80,25 @@ static void migor_ts_poscheck(struct work_struct *work)
|
|||
xpos = ((buf[11] & 0x03) << 8 | buf[10]);
|
||||
event = buf[12];
|
||||
|
||||
if (event == EVENT_PENDOWN || event == EVENT_REPEAT) {
|
||||
switch (event) {
|
||||
case EVENT_PENDOWN:
|
||||
case EVENT_REPEAT:
|
||||
input_report_key(priv->input, BTN_TOUCH, 1);
|
||||
input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
|
||||
input_report_abs(priv->input, ABS_Y, xpos);
|
||||
input_sync(priv->input);
|
||||
} else if (event == EVENT_PENUP) {
|
||||
break;
|
||||
|
||||
case EVENT_PENUP:
|
||||
input_report_key(priv->input, BTN_TOUCH, 0);
|
||||
input_sync(priv->input);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
enable_irq(priv->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t migor_ts_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct migor_ts_priv *priv = dev_id;
|
||||
|
||||
/* the touch screen controller chip is hooked up to the cpu
|
||||
* using i2c and a single interrupt line. the interrupt line
|
||||
* is pulled low whenever someone taps the screen. to deassert
|
||||
* the interrupt line we need to acknowledge the interrupt by
|
||||
* communicating with the controller over the slow i2c bus.
|
||||
*
|
||||
* we can't acknowledge from interrupt context since the i2c
|
||||
* bus controller may sleep, so we just disable the interrupt
|
||||
* here and handle the acknowledge using delayed work.
|
||||
*/
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
schedule_delayed_work(&priv->work, HZ / 20);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static int migor_ts_open(struct input_dev *dev)
|
||||
{
|
||||
struct migor_ts_priv *priv = input_get_drvdata(dev);
|
||||
|
@ -131,15 +123,6 @@ static void migor_ts_close(struct input_dev *dev)
|
|||
|
||||
disable_irq(priv->irq);
|
||||
|
||||
/* cancel pending work and wait for migor_ts_poscheck() to finish */
|
||||
if (cancel_delayed_work_sync(&priv->work)) {
|
||||
/*
|
||||
* if migor_ts_poscheck was canceled we need to enable IRQ
|
||||
* here to balance disable done in migor_ts_isr.
|
||||
*/
|
||||
enable_irq(priv->irq);
|
||||
}
|
||||
|
||||
/* disable controller */
|
||||
i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
|
||||
|
||||
|
@ -186,15 +169,15 @@ static int migor_ts_probe(struct i2c_client *client,
|
|||
|
||||
priv->client = client;
|
||||
priv->input = input;
|
||||
INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck);
|
||||
priv->irq = client->irq;
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
goto err1;
|
||||
|
||||
error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
|
||||
client->name, priv);
|
||||
error = request_threaded_irq(priv->irq, NULL, migor_ts_isr,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
client->name, priv);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
|
||||
goto err2;
|
||||
|
|
Загрузка…
Ссылка в новой задаче