|
@@ -495,6 +495,16 @@ out:
|
|
|
mutex_unlock(&ts->mutex);
|
|
|
}
|
|
|
|
|
|
+static struct attribute *tsc2005_attrs[] = {
|
|
|
+ &dev_attr_disable.attr,
|
|
|
+ &dev_attr_selftest.attr,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+static struct attribute_group tsc2005_attr_group = {
|
|
|
+ .attrs = tsc2005_attrs,
|
|
|
+};
|
|
|
+
|
|
|
static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
|
|
|
{
|
|
|
tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0);
|
|
@@ -509,144 +519,130 @@ static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
|
|
|
spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
|
|
|
}
|
|
|
|
|
|
-static struct attribute *tsc2005_attrs[] = {
|
|
|
- &dev_attr_disable.attr,
|
|
|
- &dev_attr_selftest.attr,
|
|
|
- NULL
|
|
|
-};
|
|
|
-
|
|
|
-static struct attribute_group tsc2005_attr_group = {
|
|
|
- .attrs = tsc2005_attrs,
|
|
|
-};
|
|
|
-
|
|
|
-static int __devinit tsc2005_setup(struct tsc2005 *ts,
|
|
|
- struct tsc2005_platform_data *pdata)
|
|
|
+static int __devinit tsc2005_probe(struct spi_device *spi)
|
|
|
{
|
|
|
- int r;
|
|
|
- int fudge_x;
|
|
|
- int fudge_y;
|
|
|
- int fudge_p;
|
|
|
- int p_max;
|
|
|
- int x_max;
|
|
|
- int y_max;
|
|
|
+ const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
|
|
|
+ struct tsc2005 *ts;
|
|
|
+ struct input_dev *input_dev;
|
|
|
+ unsigned int max_x, max_y, max_p;
|
|
|
+ unsigned int fudge_x, fudge_y, fudge_p;
|
|
|
+ int error;
|
|
|
|
|
|
- mutex_init(&ts->mutex);
|
|
|
+ if (!pdata) {
|
|
|
+ dev_dbg(&spi->dev, "no platform data\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
|
|
|
- tsc2005_setup_spi_xfer(ts);
|
|
|
+ fudge_x = pdata->ts_x_fudge ? : 4;
|
|
|
+ fudge_y = pdata->ts_y_fudge ? : 8;
|
|
|
+ fudge_p = pdata->ts_pressure_fudge ? : 2;
|
|
|
+ max_x = pdata->ts_x_max ? : MAX_12BIT;
|
|
|
+ max_y = pdata->ts_y_max ? : MAX_12BIT;
|
|
|
+ max_p = pdata->ts_pressure_max ? : MAX_12BIT;
|
|
|
|
|
|
- init_timer(&ts->penup_timer);
|
|
|
- setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
|
|
|
- INIT_WORK(&ts->penup_work, tsc2005_penup_work);
|
|
|
+ if (spi->irq <= 0) {
|
|
|
+ dev_dbg(&spi->dev, "no irq\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
|
|
|
- fudge_x = pdata->ts_x_fudge ? : 4;
|
|
|
- fudge_y = pdata->ts_y_fudge ? : 8;
|
|
|
- fudge_p = pdata->ts_pressure_fudge ? : 2;
|
|
|
- x_max = pdata->ts_x_max ? : MAX_12BIT;
|
|
|
- y_max = pdata->ts_y_max ? : MAX_12BIT;
|
|
|
- p_max = pdata->ts_pressure_max ? : MAX_12BIT;
|
|
|
- ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280;
|
|
|
- ts->esd_timeout = pdata->esd_timeout_ms;
|
|
|
- ts->set_reset = pdata->set_reset;
|
|
|
+ spi->mode = SPI_MODE_0;
|
|
|
+ spi->bits_per_word = 8;
|
|
|
+ if (!spi->max_speed_hz)
|
|
|
+ spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
|
|
|
|
|
|
- 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->id.bustype = BUS_SPI;
|
|
|
- ts->idev->dev.parent = &ts->spi->dev;
|
|
|
- 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, fudge_x, 0);
|
|
|
- input_set_abs_params(ts->idev, ABS_Y, 0, y_max, fudge_y, 0);
|
|
|
- input_set_abs_params(ts->idev, ABS_PRESSURE, 0, p_max, 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);
|
|
|
+ error = spi_setup(spi);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
|
|
|
- r = input_register_device(ts->idev);
|
|
|
- if (r) {
|
|
|
- dev_err(&ts->spi->dev, "input_register_device(): %d\n", r);
|
|
|
- goto err2;
|
|
|
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
|
|
|
+ input_dev = input_allocate_device();
|
|
|
+ if (!ts || !input_dev) {
|
|
|
+ error = -ENOMEM;
|
|
|
+ goto err_free_mem;
|
|
|
}
|
|
|
|
|
|
- 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);
|
|
|
+ ts->spi = spi;
|
|
|
+ ts->idev = input_dev;
|
|
|
+
|
|
|
+ ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280;
|
|
|
+ ts->esd_timeout = pdata->esd_timeout_ms;
|
|
|
+ ts->set_reset = pdata->set_reset;
|
|
|
|
|
|
- tsc2005_start_scan(ts);
|
|
|
+ mutex_init(&ts->mutex);
|
|
|
|
|
|
- if (!ts->esd_timeout || !ts->set_reset)
|
|
|
- goto done;
|
|
|
+ setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
|
|
|
+ INIT_WORK(&ts->penup_work, tsc2005_penup_work);
|
|
|
|
|
|
- /* 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_probe(struct spi_device *spi)
|
|
|
-{
|
|
|
- struct tsc2005_platform_data *pdata = spi->dev.platform_data;
|
|
|
- struct tsc2005 *ts;
|
|
|
- int r;
|
|
|
+ tsc2005_setup_spi_xfer(ts);
|
|
|
|
|
|
- if (spi->irq < 0) {
|
|
|
- dev_dbg(&spi->dev, "no irq\n");
|
|
|
- return -ENODEV;
|
|
|
+ snprintf(ts->phys, sizeof(ts->phys),
|
|
|
+ "%s/input-ts", dev_name(&spi->dev));
|
|
|
+
|
|
|
+ input_dev->name = "TSC2005 touchscreen";
|
|
|
+ input_dev->phys = ts->phys;
|
|
|
+ input_dev->id.bustype = BUS_SPI;
|
|
|
+ input_dev->dev.parent = &spi->dev;
|
|
|
+ input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
|
|
|
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
|
|
+
|
|
|
+ input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
|
|
|
+ input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
|
|
|
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
|
|
|
+
|
|
|
+ error = request_threaded_irq(spi->irq,
|
|
|
+ tsc2005_irq_handler, tsc2005_irq_thread,
|
|
|
+ IRQF_TRIGGER_RISING, "tsc2005", ts);
|
|
|
+ if (error) {
|
|
|
+ dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
|
|
|
+ goto err_free_mem;
|
|
|
}
|
|
|
|
|
|
- if (!pdata) {
|
|
|
- dev_dbg(&spi->dev, "no platform data\n");
|
|
|
- return -ENODEV;
|
|
|
+ spi_set_drvdata(spi, ts);
|
|
|
+ error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
|
|
|
+ if (error) {
|
|
|
+ dev_err(&spi->dev,
|
|
|
+ "Failed to create sysfs attributes, err: %d\n", error);
|
|
|
+ goto err_clear_drvdata;
|
|
|
}
|
|
|
|
|
|
- ts = kzalloc(sizeof(*ts), GFP_KERNEL);
|
|
|
- if (ts == NULL)
|
|
|
- return -ENOMEM;
|
|
|
+ error = input_register_device(ts->idev);
|
|
|
+ if (error) {
|
|
|
+ dev_err(&spi->dev,
|
|
|
+ "Failed to register input device, err: %d\n", error);
|
|
|
+ goto err_remove_sysfs;
|
|
|
+ }
|
|
|
|
|
|
- spi_set_drvdata(spi, ts);
|
|
|
- ts->spi = spi;
|
|
|
- spi->dev.power.power_state = PMSG_ON;
|
|
|
- spi->mode = SPI_MODE_0;
|
|
|
- spi->bits_per_word = 8;
|
|
|
- if (!spi->max_speed_hz)
|
|
|
- spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
|
|
|
- spi_setup(spi);
|
|
|
+ tsc2005_start_scan(ts);
|
|
|
|
|
|
- r = tsc2005_setup(ts, pdata);
|
|
|
- if (r) {
|
|
|
- kfree(ts);
|
|
|
- spi_set_drvdata(spi, NULL);
|
|
|
+ if (ts->esd_timeout && ts->set_reset) {
|
|
|
+ /* start the optional ESD watchdog */
|
|
|
+ mod_timer(&ts->esd_timer, round_jiffies(jiffies +
|
|
|
+ msecs_to_jiffies(ts->esd_timeout)));
|
|
|
}
|
|
|
- return r;
|
|
|
+
|
|
|
+ set_irq_wake(spi->irq, 1);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_remove_sysfs:
|
|
|
+ sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
|
|
|
+err_clear_drvdata:
|
|
|
+ spi_set_drvdata(spi, NULL);
|
|
|
+ free_irq(spi->irq, ts);
|
|
|
+err_free_mem:
|
|
|
+ input_free_device(input_dev);
|
|
|
+ kfree(ts);
|
|
|
+ return error;
|
|
|
}
|
|
|
|
|
|
static int __devexit tsc2005_remove(struct spi_device *spi)
|
|
|
{
|
|
|
struct tsc2005 *ts = spi_get_drvdata(spi);
|
|
|
|
|
|
+ sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
|
|
|
+
|
|
|
mutex_lock(&ts->mutex);
|
|
|
tsc2005_disable(ts);
|
|
|
mutex_unlock(&ts->mutex);
|
|
@@ -658,7 +654,6 @@ static int __devexit tsc2005_remove(struct spi_device *spi)
|
|
|
flush_work(&ts->esd_work);
|
|
|
flush_work(&ts->penup_work);
|
|
|
|
|
|
- sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
|
|
|
free_irq(ts->spi->irq, ts);
|
|
|
input_unregister_device(ts->idev);
|
|
|
kfree(ts);
|