]> Pileus Git - ~andy/linux/blobdiff - drivers/input/touchscreen/ucb1400_ts.c
Input: ucb1400_ts - IRQ probe fix
[~andy/linux] / drivers / input / touchscreen / ucb1400_ts.c
index e8606c48c9c31b6aa1f18736e24b967d69ee3fe6..bce018e45bce4781cb7b61519485502ff8c22171 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
@@ -27,7 +26,6 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/ac97_codec.h>
 
@@ -97,6 +95,8 @@ struct ucb1400 {
 };
 
 static int adcsync;
+static int ts_delay = 55; /* us */
+static int ts_delay_pressure;  /* us */
 
 static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
 {
@@ -128,8 +128,7 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
                if (val & UCB_ADC_DAT_VALID)
                        break;
                /* yield to other processes */
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
        }
 
        return UCB_ADC_DAT_VALUE(val);
@@ -159,6 +158,7 @@ static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
                        UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
                        UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       udelay(ts_delay_pressure);
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
 
@@ -180,7 +180,7 @@ static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
                        UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-       udelay(55);
+       udelay(ts_delay);
 
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
@@ -203,7 +203,7 @@ static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
                        UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-       udelay(55);
+       udelay(ts_delay);
 
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
 }
@@ -285,10 +285,11 @@ static int ucb1400_ts_thread(void *_ucb)
        struct ucb1400 *ucb = _ucb;
        struct task_struct *tsk = current;
        int valid = 0;
+       struct sched_param param = { .sched_priority = 1 };
 
-       tsk->policy = SCHED_FIFO;
-       tsk->rt_priority = 1;
+       sched_setscheduler(tsk, SCHED_FIFO, &param);
 
+       set_freezable();
        while (!kthread_should_stop()) {
                unsigned int x, y, p;
                long timeout;
@@ -330,10 +331,9 @@ static int ucb1400_ts_thread(void *_ucb)
                        timeout = msecs_to_jiffies(10);
                }
 
-               wait_event_interruptible_timeout(ucb->ts_wait,
+               wait_event_freezable_timeout(ucb->ts_wait,
                        ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
                        timeout);
-               try_to_freeze();
        }
 
        /* Send the "pen off" if we are stopping with the pen still active */
@@ -369,7 +369,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
 
 static int ucb1400_ts_open(struct input_dev *idev)
 {
-       struct ucb1400 *ucb = idev->private;
+       struct ucb1400 *ucb = input_get_drvdata(idev);
        int ret = 0;
 
        BUG_ON(ucb->ts_task);
@@ -385,7 +385,7 @@ static int ucb1400_ts_open(struct input_dev *idev)
 
 static void ucb1400_ts_close(struct input_dev *idev)
 {
-       struct ucb1400 *ucb = idev->private;
+       struct ucb1400 *ucb = input_get_drvdata(idev);
 
        if (ucb->ts_task)
                kthread_stop(ucb->ts_task);
@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
        unsigned long mask, timeout;
 
        mask = probe_irq_on();
-       if (!mask) {
-               probe_irq_off(mask);
-               return -EBUSY;
-       }
 
        /* Enable the ADC interrupt. */
        ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
@@ -507,14 +503,15 @@ static int ucb1400_ts_probe(struct device *dev)
        }
        printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
 
-       idev->private           = ucb;
-       idev->cdev.dev          = dev;
+       input_set_drvdata(idev, ucb);
+
+       idev->dev.parent        = dev;
        idev->name              = "UCB1400 touchscreen interface";
        idev->id.vendor         = ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
        idev->id.product        = id;
        idev->open              = ucb1400_ts_open;
        idev->close             = ucb1400_ts_close;
-       idev->evbit[0]          = BIT(EV_ABS);
+       idev->evbit[0]          = BIT_MASK(EV_ABS);
 
        ucb1400_adc_enable(ucb);
        x_res = ucb1400_ts_read_xres(ucb);
@@ -571,7 +568,15 @@ static void __exit ucb1400_ts_exit(void)
        driver_unregister(&ucb1400_ts_driver);
 }
 
-module_param(adcsync, int, 0444);
+module_param(adcsync, bool, 0444);
+MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
+
+module_param(ts_delay, int, 0444);
+MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us.");
+
+module_param(ts_delay_pressure, int, 0444);
+MODULE_PARM_DESC(ts_delay_pressure,
+                 "delay between panel setup and pressure read.  Default = 0us.");
 
 module_init(ucb1400_ts_init);
 module_exit(ucb1400_ts_exit);