X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?p=linux-2.6-omap-h63xx.git;a=blobdiff_plain;f=drivers%2Finput%2Ftouchscreen%2Ftsc210x_ts.c;fp=drivers%2Finput%2Ftouchscreen%2Ftsc210x_ts.c;h=5828b6d5514005c41a52637ddaeadddcb41a506c;hp=0000000000000000000000000000000000000000;hb=0d5f2216edfeb9904e0d6512f803b0f93871baaf;hpb=14fc69723d3442ef46f8f82b3f481e82f06a346d diff --git a/drivers/input/touchscreen/tsc210x_ts.c b/drivers/input/touchscreen/tsc210x_ts.c new file mode 100644 index 00000000000..5828b6d5514 --- /dev/null +++ b/drivers/input/touchscreen/tsc210x_ts.c @@ -0,0 +1,160 @@ +/* + * tsc210x_ts.c - touchscreen input device for TI TSC210x chips + * + * Copyright (c) 2006-2007 Andrzej Zaborowski + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this package; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include + + +/* + * 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_abs(dev, ABS_PRESSURE, 0); + input_sync(dev); + } + + input_report_key(dev, BTN_TOUCH, touching); +} + +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 (z1 != 0) + p = x * (z2 - z1) / (z1 << 4); + else + p = 1; + + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + input_report_abs(dev, ABS_PRESSURE, p); + input_sync(dev); +} + +static int tsc210x_ts_probe(struct platform_device *pdev) +{ + int status; + struct input_dev *dev; + + dev = input_allocate_device(); + if (!dev) + return -ENOMEM; + + 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, dev); + if (status) { + tsc210x_touch_cb(pdev->dev.parent, NULL, NULL); + input_free_device(dev); + return status; + } + + dev->name = "TSC210x Touchscreen"; + dev->dev.parent = &pdev->dev; + dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + dev->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); + dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + dev->phys = "tsc210x/input0"; + dev->id.bustype = BUS_HOST; + dev->id.vendor = 0x0001; + dev->id.product = 0x2100; + dev->id.version = 0x0001; + + status = input_register_device(dev); + if (status) { + tsc210x_coords_cb(pdev->dev.parent, NULL, NULL); + tsc210x_touch_cb(pdev->dev.parent, NULL, NULL); + input_free_device(dev); + return status; + } + + platform_set_drvdata(pdev, dev); + printk(KERN_INFO "TSC210x touchscreen initialised\n"); + return 0; +} + +static int __exit tsc210x_ts_remove(struct platform_device *pdev) +{ + struct input_dev *dev = platform_get_drvdata(pdev); + + 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); + + return 0; +} + +static struct platform_driver tsc210x_ts_driver = { + .probe = tsc210x_ts_probe, + .remove = __exit_p(tsc210x_ts_remove), + /* Nothing to do on suspend/resume */ + .driver = { + .name = "tsc210x-ts", + .owner = THIS_MODULE, + }, +}; + +static int __init tsc210x_ts_init(void) +{ + /* 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_exit(tsc210x_ts_exit); + +MODULE_AUTHOR("Andrzej Zaborowski"); +MODULE_DESCRIPTION("Touchscreen input driver for TI TSC2101/2102."); +MODULE_LICENSE("GPL");