static void tsc2005_esd_work(struct work_struct *work) { struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); u16 r; mutex_lock(&ts->mutex); if (ts->disable_depth) goto out; /* * If we cannot read our known value from configuration register 0 then * reset the controller as if from power-up and start scanning again. */ tsc2005_read(ts, TSC2005_REG_CFR0, &r); if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); ts->set_reset(0); tsc2005_update_pen_state(ts, 0, 0, 0); msleep(1); /* only 10us required */ ts->set_reset(1); tsc2005_start_scan(ts); } /* re-arm the watchdog */ mod_timer(&ts->esd_timer, round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); out: mutex_unlock(&ts->mutex); }
/* must be called with mutex held */ static void tsc2005_enable(struct tsc2005 *ts) { if (--ts->disable_depth != 0) return; tsc2005_start_scan(ts); enable_irq(ts->spi->irq); if (!ts->esd_timeout) return; mod_timer(&ts->esd_timer, round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); }
static void tsc2005_enable(struct tsc2005 *ts) { if (ts->disable_depth != 1) goto out; if (ts->esd_timeout) { unsigned long wdj = msecs_to_jiffies(ts->esd_timeout); ts->esd_timer.expires = round_jiffies(jiffies+wdj); add_timer(&ts->esd_timer); } tsc2005_start_scan(ts); enable_irq(ts->spi->irq); out: --ts->disable_depth; }
static void tsc2005_rst_handler(struct work_struct *work) { u16 reg_val; struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); unsigned long wdj; mutex_lock(&ts->mutex); /* If we are disabled, or the a touch has been detected, * then ignore this timeout. The enable will restart the * watchdog, as it restarts scanning */ if (ts->disable_depth) goto out; /* If we cannot read our known value from configuration register 0 * then reset the controller as if from power-up and start * scanning again. Always re-arm the watchdog. */ tsc2005_read(ts, TSC2005_REG_CFR0, ®_val); if ((reg_val ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { dev_info(&ts->spi->dev, "TSC not responding, resetting.\n"); /* If this timer kicked in, the penup timer, if ever active * at all, must have expired ages ago, so no need to del it. */ ts->set_reset(0); if (ts->sample_sent) { tsc2005_ts_update_pen_state(ts, 0, 0, 0); ts->sample_sent = 0; } ts->spi_pending = 0; msleep(1); /* only 10us required */ ts->set_reset(1); tsc2005_start_scan(ts); } wdj = msecs_to_jiffies(ts->esd_timeout); mod_timer(&ts->esd_timer, round_jiffies(jiffies+wdj)); out: mutex_unlock(&ts->mutex); }
static int __devinit tsc2005_setup(struct tsc2005 *ts, struct tsc2005_platform_data *pdata) { int r; int x_max; int y_max; mutex_init(&ts->mutex); tsc2005_setup_spi_xfer(ts); init_timer(&ts->penup_timer); setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); INIT_WORK(&ts->penup_work, tsc2005_penup_work); ts->fudge_x = pdata->ts_x_fudge ? : 4; ts->fudge_y = pdata->ts_y_fudge ? : 8; ts->fudge_p = pdata->ts_pressure_fudge ? : 2; x_max = pdata->ts_x_max ? : MAX_12BIT; y_max = pdata->ts_y_max ? : MAX_12BIT; ts->p_max = pdata->ts_pressure_max ? : MAX_12BIT; ts->ts_pressure = 1200; ts->x_plate_ohm = pdata->ts_x_plate_ohm; ts->esd_timeout = pdata->esd_timeout_ms; ts->set_reset = pdata->set_reset; ts->idev = input_allocate_device(); if (ts->idev == NULL) return -ENOMEM; ts->idev->name = "TSC2005 touchscreen"; snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", dev_name(&ts->spi->dev)); ts->idev->phys = ts->phys; ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); ts->idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(ts->idev, ABS_X, 0, x_max, ts->fudge_x, 0); input_set_abs_params(ts->idev, ABS_Y, 0, y_max, ts->fudge_y, 0); input_set_abs_params(ts->idev, ABS_PRESSURE, 0, ts->p_max, ts->fudge_p, 0); r = request_threaded_irq(ts->spi->irq, tsc2005_irq_handler, tsc2005_irq_thread, IRQF_TRIGGER_RISING, "tsc2005", ts); if (r) { dev_err(&ts->spi->dev, "request_threaded_irq(): %d\n", r); goto err1; } set_irq_wake(ts->spi->irq, 1); r = input_register_device(ts->idev); if (r) { dev_err(&ts->spi->dev, "input_register_device(): %d\n", r); goto err2; } r = sysfs_create_group(&ts->spi->dev.kobj, &tsc2005_attr_group); if (r) dev_warn(&ts->spi->dev, "sysfs entry creation failed: %d\n", r); tsc2005_start_scan(ts); if (!ts->esd_timeout || !ts->set_reset) goto done; /* start the optional ESD watchdog */ setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); INIT_WORK(&ts->esd_work, tsc2005_esd_work); mod_timer(&ts->esd_timer, round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); done: return 0; err2: free_irq(ts->spi->irq, ts); err1: input_free_device(ts->idev); return r; }
static int __devinit tsc2005_ts_init(struct tsc2005 *ts, struct tsc2005_platform_data *pdata) { struct input_dev *idev; int r; int x_max, y_max; init_timer(&ts->penup_timer); setup_timer(&ts->penup_timer, tsc2005_ts_penup_timer_handler, (unsigned long)ts); spin_lock_init(&ts->lock); mutex_init(&ts->mutex); ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; ts->hw_avg_max = pdata->ts_hw_avg; ts->stab_time = pdata->ts_stab_time; x_max = pdata->ts_x_max ? : 4096; ts->fudge_x = pdata->ts_x_fudge ? : 4; y_max = pdata->ts_y_max ? : 4096; ts->fudge_y = pdata->ts_y_fudge ? : 8; ts->p_max = pdata->ts_pressure_max ? : MAX_12BIT; ts->touch_pressure = pdata->ts_touch_pressure ? : ts->p_max; ts->fudge_p = pdata->ts_pressure_fudge ? : 2; ts->set_reset = pdata->set_reset; if (prescale) { x_max = x_size; y_max = y_size; } idev = input_allocate_device(); if (idev == NULL) { r = -ENOMEM; goto err1; } idev->name = "TSC2005 touchscreen"; snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts", ts->spi->dev.bus_id); idev->phys = ts->phys; idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | BIT_MASK(ABS_PRESSURE); idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); ts->idev = idev; tsc2005_ts_setup_spi_xfer(ts); input_set_abs_params(idev, ABS_X, 0, x_max, ts->fudge_x, 0); input_set_abs_params(idev, ABS_Y, 0, y_max, ts->fudge_y, 0); input_set_abs_params(idev, ABS_PRESSURE, 0, ts->p_max, ts->fudge_p, 0); tsc2005_start_scan(ts); r = request_irq(ts->spi->irq, tsc2005_ts_irq_handler, (((TSC2005_CFR2_INITVALUE & TSC2005_CFR2_IRQ_MASK) == TSC2005_CFR2_IRQ_PENDAV) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING) | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "tsc2005", ts); if (r < 0) { dev_err(&ts->spi->dev, "unable to get DAV IRQ"); goto err2; } set_irq_wake(ts->spi->irq, 1); r = input_register_device(idev); if (r < 0) { dev_err(&ts->spi->dev, "can't register touchscreen device\n"); goto err3; } /* We can tolerate these failing */ r = device_create_file(&ts->spi->dev, &dev_attr_ts_ctrl_selftest); if (r < 0) dev_warn(&ts->spi->dev, "can't create sysfs file for %s: %d\n", dev_attr_ts_ctrl_selftest.attr.name, r); r = device_create_file(&ts->spi->dev, &dev_attr_pen_down); if (r < 0) dev_warn(&ts->spi->dev, "can't create sysfs file for %s: %d\n", dev_attr_pen_down.attr.name, r); r = device_create_file(&ts->spi->dev, &dev_attr_disable_ts); if (r < 0) dev_warn(&ts->spi->dev, "can't create sysfs file for %s: %d\n", dev_attr_disable_ts.attr.name, r); /* Finally, configure and start the optional EDD watchdog. */ ts->esd_timeout = pdata->esd_timeout; if (ts->esd_timeout && ts->set_reset) { unsigned long wdj; setup_timer(&ts->esd_timer, tsc2005_esd_timer_handler, (unsigned long)ts); INIT_WORK(&ts->esd_work, tsc2005_rst_handler); wdj = msecs_to_jiffies(ts->esd_timeout); ts->esd_timer.expires = round_jiffies(jiffies+wdj); add_timer(&ts->esd_timer); } return 0; err3: free_irq(ts->spi->irq, ts); err2: tsc2005_stop_scan(ts); input_free_device(idev); err1: return r; }