Input: migor-ts - convert to a threaded IRQ
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
@@ -36,7 +36,6 @@
|
|||||||
struct migor_ts_priv {
|
struct migor_ts_priv {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
struct delayed_work work;
|
|
||||||
int irq;
|
int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,15 +43,24 @@ static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11,
|
|||||||
0x01, 0x06, 0x07, };
|
0x01, 0x06, 0x07, };
|
||||||
static const u_int8_t migor_ts_dis_seq[17] = { };
|
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 *priv = dev_id;
|
||||||
struct migor_ts_priv,
|
|
||||||
work.work);
|
|
||||||
unsigned short xpos, ypos;
|
unsigned short xpos, ypos;
|
||||||
unsigned char event;
|
unsigned char event;
|
||||||
u_int8_t buf[16];
|
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));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
/* Set Index 0 */
|
/* Set Index 0 */
|
||||||
@@ -72,41 +80,25 @@ static void migor_ts_poscheck(struct work_struct *work)
|
|||||||
xpos = ((buf[11] & 0x03) << 8 | buf[10]);
|
xpos = ((buf[11] & 0x03) << 8 | buf[10]);
|
||||||
event = buf[12];
|
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_key(priv->input, BTN_TOUCH, 1);
|
||||||
input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
|
input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
|
||||||
input_report_abs(priv->input, ABS_Y, xpos);
|
input_report_abs(priv->input, ABS_Y, xpos);
|
||||||
input_sync(priv->input);
|
input_sync(priv->input);
|
||||||
} else if (event == EVENT_PENUP) {
|
break;
|
||||||
|
|
||||||
|
case EVENT_PENUP:
|
||||||
input_report_key(priv->input, BTN_TOUCH, 0);
|
input_report_key(priv->input, BTN_TOUCH, 0);
|
||||||
input_sync(priv->input);
|
input_sync(priv->input);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int migor_ts_open(struct input_dev *dev)
|
static int migor_ts_open(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
struct migor_ts_priv *priv = input_get_drvdata(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);
|
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 */
|
/* disable controller */
|
||||||
i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
|
i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
|
||||||
|
|
||||||
@@ -186,14 +169,14 @@ static int migor_ts_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
priv->client = client;
|
priv->client = client;
|
||||||
priv->input = input;
|
priv->input = input;
|
||||||
INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck);
|
|
||||||
priv->irq = client->irq;
|
priv->irq = client->irq;
|
||||||
|
|
||||||
error = input_register_device(input);
|
error = input_register_device(input);
|
||||||
if (error)
|
if (error)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
|
error = request_threaded_irq(priv->irq, NULL, migor_ts_isr,
|
||||||
|
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||||
client->name, priv);
|
client->name, priv);
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
|
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
|
||||||
|
Reference in New Issue
Block a user