Example #1
0
static void tsc200x_penup_timer(unsigned long data)
{
    struct tsc200x *ts = (struct tsc200x *)data;
    unsigned long flags;

    spin_lock_irqsave(&ts->lock, flags);
    tsc200x_update_pen_state(ts, 0, 0, 0);
    spin_unlock_irqrestore(&ts->lock, flags);
}
Example #2
0
static void tsc200x_penup_timer(struct timer_list *t)
{
	struct tsc200x *ts = from_timer(ts, t, penup_timer);
	unsigned long flags;

	spin_lock_irqsave(&ts->lock, flags);
	tsc200x_update_pen_state(ts, 0, 0, 0);
	spin_unlock_irqrestore(&ts->lock, flags);
}
Example #3
0
static void tsc200x_esd_work(struct work_struct *work)
{
    struct tsc200x *ts = container_of(work, struct tsc200x, esd_work.work);
    int error;
    unsigned int r;

    if (!mutex_trylock(&ts->mutex)) {
        /*
         * If the mutex is taken, it means that disable or enable is in
         * progress. In that case just reschedule the work. If the work
         * is not needed, it will be canceled by disable.
         */
        goto reschedule;
    }

    if (time_is_after_jiffies(ts->last_valid_interrupt +
                              msecs_to_jiffies(ts->esd_timeout)))
        goto out;

    /* We should be able to read register without disabling interrupts. */
    error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r);
    if (!error &&
            !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) {
        goto out;
    }

    /*
     * If we could not read our known value from configuration register 0
     * then we should reset the controller as if from power-up and start
     * scanning again.
     */
    dev_info(ts->dev, "TSC200X not responding - resetting\n");

    disable_irq(ts->irq);
    del_timer_sync(&ts->penup_timer);

    tsc200x_update_pen_state(ts, 0, 0, 0);

    tsc200x_set_reset(ts, false);
    usleep_range(100, 500); /* only 10us required */
    tsc200x_set_reset(ts, true);

    enable_irq(ts->irq);
    tsc200x_start_scan(ts);

out:
    mutex_unlock(&ts->mutex);
reschedule:
    /* re-arm the watchdog */
    schedule_delayed_work(&ts->esd_work,
                          round_jiffies_relative(
                              msecs_to_jiffies(ts->esd_timeout)));
}
Example #4
0
static irqreturn_t tsc200x_irq_thread(int irq, void *_ts)
{
    struct tsc200x *ts = _ts;
    unsigned long flags;
    unsigned int pressure;
    struct tsc200x_data tsdata;
    int error;

    /* read the coordinates */
    error = regmap_bulk_read(ts->regmap, TSC200X_REG_X, &tsdata,
                             TSC200X_DATA_REGS);
    if (unlikely(error))
        goto out;

    /* validate position */
    if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
        goto out;

    /* Skip reading if the pressure components are out of range */
    if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
        goto out;
    if (unlikely(tsdata.z1 >= tsdata.z2))
        goto out;

    /*
    * Skip point if this is a pen down with the exact same values as
    * the value before pen-up - that implies SPI fed us stale data
    */
    if (!ts->pen_down &&
            ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
            ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
        goto out;
    }

    /*
     * At this point we are happy we have a valid and useful reading.
     * Remember it for later comparisons. We may now begin downsampling.
     */
    ts->in_x = tsdata.x;
    ts->in_y = tsdata.y;
    ts->in_z1 = tsdata.z1;
    ts->in_z2 = tsdata.z2;

    /* Compute touch pressure resistance using equation #1 */
    pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
    pressure = pressure * ts->x_plate_ohm / 4096;
    if (unlikely(pressure > MAX_12BIT))
        goto out;

    spin_lock_irqsave(&ts->lock, flags);

    tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
    mod_timer(&ts->penup_timer,
              jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS));

    spin_unlock_irqrestore(&ts->lock, flags);

    ts->last_valid_interrupt = jiffies;
out:
    return IRQ_HANDLED;
}