Beispiel #1
0
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);
}
Beispiel #2
0
/* 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)));
}
Beispiel #3
0
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;
}
Beispiel #4
0
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, &reg_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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}