/*
- * input/touchscreen/tsc210x_ts.c
- *
- * Touchscreen input device driver for the TSC 2101/2102 chips.
+ * tsc210x_ts.c - touchscreen input device for TI TSC210x chips
*
* Copyright (c) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
*
#include <linux/spi/tsc210x.h>
-static void tsc210x_touch(struct input_dev *dev, int touching)
+
+/*
+ * The sensor ADC on tsc210x chips is most often used with the smart
+ * touchscreen controller. Those controllers can be made to improve
+ * sample quality directly by multi-sampling and by taking the mean or
+ * median of various numbers of samples. They also take X, Y, and
+ * pressure measurements automatically, so this driver has relatively
+ * little to do.
+ *
+ * There are a few chips in this family that don't have quite the same
+ * touchscreen interface, e.g. no "median" mode.
+ */
+
+static void tsc210x_touch(void *context, int touching)
{
+ struct input_dev *dev = context;
+
if (!touching) {
input_report_abs(dev, ABS_X, 0);
input_report_abs(dev, ABS_Y, 0);
input_report_key(dev, BTN_TOUCH, touching);
}
-static void tsc210x_coords(struct input_dev *dev, int x, int y, int z1, int z2)
+static void tsc210x_coords(void *context, int x, int y, int z1, int z2)
{
+ struct input_dev *dev = context;
int p;
/* Calculate the touch resistance a la equation #1 */
if (!dev)
return -ENOMEM;
- status = tsc210x_touch_cb(pdev->dev.parent,
- (tsc210x_touch_t) tsc210x_touch, dev);
+ status = tsc210x_touch_cb(pdev->dev.parent, tsc210x_touch, dev);
if (status) {
input_free_device(dev);
return status;
}
- status = tsc210x_coords_cb(pdev->dev.parent,
- (tsc210x_coords_t) tsc210x_coords, dev);
+ status = tsc210x_coords_cb(pdev->dev.parent, tsc210x_coords, dev);
if (status) {
- tsc210x_touch_cb(pdev->dev.parent, 0, 0);
+ tsc210x_touch_cb(pdev->dev.parent, NULL, NULL);
input_free_device(dev);
return status;
}
status = input_register_device(dev);
if (status) {
- tsc210x_coords_cb(pdev->dev.parent, 0, 0);
- tsc210x_touch_cb(pdev->dev.parent, 0, 0);
+ tsc210x_coords_cb(pdev->dev.parent, NULL, NULL);
+ tsc210x_touch_cb(pdev->dev.parent, NULL, NULL);
input_free_device(dev);
return status;
}
return 0;
}
-static int tsc210x_ts_remove(struct platform_device *pdev)
+static int __exit tsc210x_ts_remove(struct platform_device *pdev)
{
- struct input_dev *dev = (struct input_dev *)
- platform_get_drvdata(pdev);
+ struct input_dev *dev = platform_get_drvdata(pdev);
- tsc210x_touch_cb(pdev->dev.parent, 0, 0);
- tsc210x_coords_cb(pdev->dev.parent, 0, 0);
- platform_set_drvdata(pdev, 0);
+ tsc210x_touch_cb(pdev->dev.parent, NULL, NULL);
+ tsc210x_coords_cb(pdev->dev.parent, NULL, NULL);
+ platform_set_drvdata(pdev, NULL);
input_unregister_device(dev);
input_free_device(dev);
}
static struct platform_driver tsc210x_ts_driver = {
- .probe = tsc210x_ts_probe,
- .remove = tsc210x_ts_remove,
+ .probe = tsc210x_ts_probe,
+ .remove = __exit_p(tsc210x_ts_remove),
/* Nothing to do on suspend/resume */
.driver = {
.name = "tsc210x-ts",
static int __init tsc210x_ts_init(void)
{
- int ret;
-
- ret = platform_driver_register(&tsc210x_ts_driver);
- if (ret)
- return -ENODEV;
-
- return 0;
+ /* can't use driver_probe() here since the parent device
+ * gets registered "late"
+ */
+ return platform_driver_register(&tsc210x_ts_driver);
}
+module_init(tsc210x_ts_init);
static void __exit tsc210x_ts_exit(void)
{
platform_driver_unregister(&tsc210x_ts_driver);
}
-
-module_init(tsc210x_ts_init);
module_exit(tsc210x_ts_exit);
MODULE_AUTHOR("Andrzej Zaborowski");