From af675147381912b23274980af11f4cf60cdad788 Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Wed, 7 Dec 2016 10:53:08 +0800 Subject: [PATCH] input: touchscreen: fix tp gslxxxx irq number bug gslxxxx wrong irq number with the same vopb, may cause vopb abnormal. ts->irq is gpio number, gslxxxx irq number is ts->client->irq ts->client->irq = gpio_to_irq(ts->irq) Change-Id: Ic1f6a46437a2a185f3218d3f0406deeddd9d670a Signed-off-by: Bin Yang --- drivers/input/touchscreen/gsl3673.c | 40 +++++++++++++++++++++++++---- drivers/input/touchscreen/gslx680.c | 19 +++++++------- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/input/touchscreen/gsl3673.c b/drivers/input/touchscreen/gsl3673.c index b5153298334a..87d5256f27bf 100644 --- a/drivers/input/touchscreen/gsl3673.c +++ b/drivers/input/touchscreen/gsl3673.c @@ -200,6 +200,8 @@ struct gsl_ts { u8 device_id; int irq; int rst; + int flag_irq_is_disable; + spinlock_t irq_lock; struct tp_device tp; }; @@ -739,6 +741,30 @@ static void report_data(struct gsl_ts *ts, u16 x, u16 y, u8 pressure, u8 id) #endif } +void ts_irq_disable(struct gsl_ts *ts) +{ + unsigned long irqflags; + + spin_lock_irqsave(&ts->irq_lock, irqflags); + if (!ts->flag_irq_is_disable) { + disable_irq_nosync(ts->client->irq); + ts->flag_irq_is_disable = 1; + } + spin_unlock_irqrestore(&ts->irq_lock, irqflags); +} + +void ts_irq_enable(struct gsl_ts *ts) +{ + unsigned long irqflags = 0; + + spin_lock_irqsave(&ts->irq_lock, irqflags); + if (ts->flag_irq_is_disable) { + enable_irq(ts->client->irq); + ts->flag_irq_is_disable = 0; + } + spin_unlock_irqrestore(&ts->irq_lock, irqflags); +} + static void gsl3673_ts_worker(struct work_struct *work) { int rc, i; @@ -853,7 +879,8 @@ schedule: i2c_lock_flag = 0; i2c_lock_schedule: #endif - enable_irq(ts->irq); + ts_irq_enable(ts); + } #ifdef GSL_MONITOR @@ -921,7 +948,7 @@ static irqreturn_t gsl_ts_irq(int irq, void *dev_id) { struct gsl_ts *ts = (struct gsl_ts *)dev_id; - disable_irq_nosync(ts->irq); + ts_irq_disable(ts); if (!work_pending(&ts->work)) queue_work(ts->wq, &ts->work); return IRQ_HANDLED; @@ -1009,7 +1036,9 @@ static int gsl_ts_suspend(struct device *dev) #ifdef GSL_MONITOR cancel_delayed_work_sync(&gsl_monitor_work); #endif - disable_irq_nosync(ts->irq); + ts_irq_disable(ts); + cancel_work_sync(&ts->work); + gsl3673_shutdown_low(); #ifdef SLEEP_CLEAR_POINT msleep(10); @@ -1058,8 +1087,8 @@ static int gsl_ts_resume(struct device *dev) #ifdef GSL_MONITOR queue_delayed_work(gsl_monitor_workqueue, &gsl_monitor_work, 300); #endif - disable_irq_nosync(ts->irq); - enable_irq(ts->irq); + ts_irq_enable(ts); + return 0; } @@ -1118,6 +1147,7 @@ static int gsl_ts_probe(struct i2c_client *client, goto error_init_chip_fail; } check_mem_data(ts->client); + spin_lock_init(&ts->irq_lock); client->irq = gpio_to_irq(ts->irq); rc = devm_request_irq(&client->dev, client->irq, gsl_ts_irq, IRQF_TRIGGER_RISING, client->name, ts); diff --git a/drivers/input/touchscreen/gslx680.c b/drivers/input/touchscreen/gslx680.c index 2742c35697eb..1908486d6e0b 100644 --- a/drivers/input/touchscreen/gslx680.c +++ b/drivers/input/touchscreen/gslx680.c @@ -1174,7 +1174,7 @@ static void gslX680_ts_worker(struct work_struct *work) i2c_lock_flag = 0; i2c_lock_schedule: #endif - enable_irq(ts->irq); + enable_irq(ts->client->irq); } @@ -1305,7 +1305,7 @@ static irqreturn_t gsl_ts_irq(int irq, void *dev_id) struct gsl_ts *ts = (struct gsl_ts *)dev_id; //print_info("========gslX680 Interrupt=========\n"); - disable_irq_nosync(ts->irq); + disable_irq_nosync(ts->client->irq); if (!work_pending(&ts->work)) { queue_work(ts->wq, &ts->work); @@ -1515,7 +1515,7 @@ static int gsl_ts_early_suspend(struct tp_device *tp_d) cancel_delayed_work_sync(&ts->gsl_monitor_work); #endif - disable_irq_nosync(ts->irq); + disable_irq_nosync(ts->client->irq); #ifdef SLEEP_CLEAR_POINT msleep(10); @@ -1567,8 +1567,8 @@ static int gsl_ts_late_resume(struct tp_device *tp_d) printk("gsl_ts_resume () : queue gsl_monitor_work\n"); queue_delayed_work(gsl_monitor_workqueue, &ts->gsl_monitor_work, 300); #endif - disable_irq_nosync(ts->irq); - enable_irq(ts->irq); + disable_irq_nosync(ts->client->irq); + enable_irq(ts->client->irq); return 0; } @@ -1585,7 +1585,7 @@ static void gsl_ts_early_suspend(struct early_suspend *h) cancel_delayed_work_sync(&ts->gsl_monitor_work); #endif - disable_irq_nosync(ts->irq); + disable_irq_nosync(ts->client->irq); #ifdef SLEEP_CLEAR_POINT msleep(10); @@ -1638,8 +1638,9 @@ static void gsl_ts_late_resume(struct early_suspend *h) printk("gsl_ts_resume () : queue gsl_monitor_work\n"); queue_delayed_work(gsl_monitor_workqueue, &ts->gsl_monitor_work, 300); #endif - disable_irq_nosync(ts->irq); - enable_irq(ts->irq); + disable_irq_nosync(ts->client->irq); + enable_irq(ts->client->irq); + } #endif @@ -1766,7 +1767,7 @@ static int gsl_ts_remove(struct i2c_client *client) device_init_wakeup(&client->dev, 0); cancel_work_sync(&ts->work); - free_irq(ts->irq, ts); + free_irq(ts->client->irq, ts); destroy_workqueue(ts->wq); //device_remove_file(&ts->input->dev, &dev_attr_debug_enable); -- 2.34.1