diff options
Diffstat (limited to 'drivers/input/touchscreen/tnetv107x-ts.c')
-rw-r--r-- | drivers/input/touchscreen/tnetv107x-ts.c | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c deleted file mode 100644 index c47827a26e3c..000000000000 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Texas Instruments TNETV107X Touchscreen Driver - * - * Copyright (C) 2010 Texas Instruments - * - * This program 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/errno.h> -#include <linux/input.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/ctype.h> -#include <linux/io.h> -#include <linux/clk.h> - -#include <mach/tnetv107x.h> - -#define TSC_PENUP_POLL (HZ / 5) -#define IDLE_TIMEOUT 100 /* msec */ - -/* - * The first and last samples of a touch interval are usually garbage and need - * to be filtered out with these devices. The following definitions control - * the number of samples skipped. - */ -#define TSC_HEAD_SKIP 1 -#define TSC_TAIL_SKIP 1 -#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) -#define TSC_SAMPLES (TSC_SKIP + 1) - -/* Register Offsets */ -struct tsc_regs { - u32 rev; - u32 tscm; - u32 bwcm; - u32 swc; - u32 adcchnl; - u32 adcdata; - u32 chval[4]; -}; - -/* TSC Mode Configuration Register (tscm) bits */ -#define WMODE BIT(0) -#define TSKIND BIT(1) -#define ZMEASURE_EN BIT(2) -#define IDLE BIT(3) -#define TSC_EN BIT(4) -#define STOP BIT(5) -#define ONE_SHOT BIT(6) -#define SINGLE BIT(7) -#define AVG BIT(8) -#define AVGNUM(x) (((x) & 0x03) << 9) -#define PVSTC(x) (((x) & 0x07) << 11) -#define PON BIT(14) -#define PONBG BIT(15) -#define AFERST BIT(16) - -/* ADC DATA Capture Register bits */ -#define DATA_VALID BIT(16) - -/* Register Access Macros */ -#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) -#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); -#define tsc_set_bits(ts, reg, val) \ - tsc_write(ts, reg, tsc_read(ts, reg) | (val)) -#define tsc_clr_bits(ts, reg, val) \ - tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) - -struct sample { - int x, y, p; -}; - -struct tsc_data { - struct input_dev *input_dev; - struct resource *res; - struct tsc_regs __iomem *regs; - struct timer_list timer; - spinlock_t lock; - struct clk *clk; - struct device *dev; - int sample_count; - struct sample samples[TSC_SAMPLES]; - int tsc_irq; -}; - -static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) -{ - int x, y, z1, z2, t, p = 0; - u32 val; - - val = tsc_read(ts, chval[0]); - if (val & DATA_VALID) - x = val & 0xffff; - else - return -EINVAL; - - y = tsc_read(ts, chval[1]) & 0xffff; - z1 = tsc_read(ts, chval[2]) & 0xffff; - z2 = tsc_read(ts, chval[3]) & 0xffff; - - if (z1) { - t = ((600 * x) * (z2 - z1)); - p = t / (u32) (z1 << 12); - if (p < 0) - p = 0; - } - - sample->x = x; - sample->y = y; - sample->p = p; - - return 0; -} - -static void tsc_poll(unsigned long data) -{ - struct tsc_data *ts = (struct tsc_data *)data; - unsigned long flags; - int i, val, x, y, p; - - spin_lock_irqsave(&ts->lock, flags); - - if (ts->sample_count >= TSC_SKIP) { - input_report_abs(ts->input_dev, ABS_PRESSURE, 0); - input_report_key(ts->input_dev, BTN_TOUCH, 0); - input_sync(ts->input_dev); - } else if (ts->sample_count > 0) { - /* - * A touch event lasted less than our skip count. Salvage and - * report anyway. - */ - for (i = 0, val = 0; i < ts->sample_count; i++) - val += ts->samples[i].x; - x = val / ts->sample_count; - - for (i = 0, val = 0; i < ts->sample_count; i++) - val += ts->samples[i].y; - y = val / ts->sample_count; - - for (i = 0, val = 0; i < ts->sample_count; i++) - val += ts->samples[i].p; - p = val / ts->sample_count; - - input_report_abs(ts->input_dev, ABS_X, x); - input_report_abs(ts->input_dev, ABS_Y, y); - input_report_abs(ts->input_dev, ABS_PRESSURE, p); - input_report_key(ts->input_dev, BTN_TOUCH, 1); - input_sync(ts->input_dev); - } - - ts->sample_count = 0; - - spin_unlock_irqrestore(&ts->lock, flags); -} - -static irqreturn_t tsc_irq(int irq, void *dev_id) -{ - struct tsc_data *ts = (struct tsc_data *)dev_id; - struct sample *sample; - int index; - - spin_lock(&ts->lock); - - index = ts->sample_count % TSC_SAMPLES; - sample = &ts->samples[index]; - if (tsc_read_sample(ts, sample) < 0) - goto out; - - if (++ts->sample_count >= TSC_SKIP) { - index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; - sample = &ts->samples[index]; - - input_report_abs(ts->input_dev, ABS_X, sample->x); - input_report_abs(ts->input_dev, ABS_Y, sample->y); - input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); - if (ts->sample_count == TSC_SKIP) - input_report_key(ts->input_dev, BTN_TOUCH, 1); - input_sync(ts->input_dev); - } - mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); -out: - spin_unlock(&ts->lock); - return IRQ_HANDLED; -} - -static int tsc_start(struct input_dev *dev) -{ - struct tsc_data *ts = input_get_drvdata(dev); - unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); - u32 val; - - clk_enable(ts->clk); - - /* Go to idle mode, before any initialization */ - while (time_after(timeout, jiffies)) { - if (tsc_read(ts, tscm) & IDLE) - break; - } - - if (time_before(timeout, jiffies)) { - dev_warn(ts->dev, "timeout waiting for idle\n"); - clk_disable(ts->clk); - return -EIO; - } - - /* Configure TSC Control register*/ - val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); - tsc_write(ts, tscm, val); - - /* Bring TSC out of reset: Clear AFE reset bit */ - val &= ~(AFERST); - tsc_write(ts, tscm, val); - - /* Configure all pins for hardware control*/ - tsc_write(ts, bwcm, 0); - - /* Finally enable the TSC */ - tsc_set_bits(ts, tscm, TSC_EN); - - return 0; -} - -static void tsc_stop(struct input_dev *dev) -{ - struct tsc_data *ts = input_get_drvdata(dev); - - tsc_clr_bits(ts, tscm, TSC_EN); - synchronize_irq(ts->tsc_irq); - del_timer_sync(&ts->timer); - clk_disable(ts->clk); -} - -static int tsc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct tsc_data *ts; - int error = 0; - u32 rev = 0; - - ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); - if (!ts) { - dev_err(dev, "cannot allocate device info\n"); - return -ENOMEM; - } - - ts->dev = dev; - spin_lock_init(&ts->lock); - setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); - platform_set_drvdata(pdev, ts); - - ts->tsc_irq = platform_get_irq(pdev, 0); - if (ts->tsc_irq < 0) { - dev_err(dev, "cannot determine device interrupt\n"); - error = -ENODEV; - goto error_res; - } - - ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!ts->res) { - dev_err(dev, "cannot determine register area\n"); - error = -ENODEV; - goto error_res; - } - - if (!request_mem_region(ts->res->start, resource_size(ts->res), - pdev->name)) { - dev_err(dev, "cannot claim register memory\n"); - ts->res = NULL; - error = -EINVAL; - goto error_res; - } - - ts->regs = ioremap(ts->res->start, resource_size(ts->res)); - if (!ts->regs) { - dev_err(dev, "cannot map register memory\n"); - error = -ENOMEM; - goto error_map; - } - - ts->clk = clk_get(dev, NULL); - if (IS_ERR(ts->clk)) { - dev_err(dev, "cannot claim device clock\n"); - error = PTR_ERR(ts->clk); - goto error_clk; - } - - error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, IRQF_ONESHOT, - dev_name(dev), ts); - if (error < 0) { - dev_err(ts->dev, "Could not allocate ts irq\n"); - goto error_irq; - } - - ts->input_dev = input_allocate_device(); - if (!ts->input_dev) { - dev_err(dev, "cannot allocate input device\n"); - error = -ENOMEM; - goto error_input; - } - input_set_drvdata(ts->input_dev, ts); - - ts->input_dev->name = pdev->name; - ts->input_dev->id.bustype = BUS_HOST; - ts->input_dev->dev.parent = &pdev->dev; - ts->input_dev->open = tsc_start; - ts->input_dev->close = tsc_stop; - - clk_enable(ts->clk); - rev = tsc_read(ts, rev); - ts->input_dev->id.product = ((rev >> 8) & 0x07); - ts->input_dev->id.version = ((rev >> 16) & 0xfff); - clk_disable(ts->clk); - - __set_bit(EV_KEY, ts->input_dev->evbit); - __set_bit(EV_ABS, ts->input_dev->evbit); - __set_bit(BTN_TOUCH, ts->input_dev->keybit); - - input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); - input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); - input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); - - error = input_register_device(ts->input_dev); - if (error < 0) { - dev_err(dev, "failed input device registration\n"); - goto error_reg; - } - - return 0; - -error_reg: - input_free_device(ts->input_dev); -error_input: - free_irq(ts->tsc_irq, ts); -error_irq: - clk_put(ts->clk); -error_clk: - iounmap(ts->regs); -error_map: - release_mem_region(ts->res->start, resource_size(ts->res)); -error_res: - kfree(ts); - - return error; -} - -static int tsc_remove(struct platform_device *pdev) -{ - struct tsc_data *ts = platform_get_drvdata(pdev); - - input_unregister_device(ts->input_dev); - free_irq(ts->tsc_irq, ts); - clk_put(ts->clk); - iounmap(ts->regs); - release_mem_region(ts->res->start, resource_size(ts->res)); - kfree(ts); - - return 0; -} - -static struct platform_driver tsc_driver = { - .probe = tsc_probe, - .remove = tsc_remove, - .driver.name = "tnetv107x-ts", - .driver.owner = THIS_MODULE, -}; -module_platform_driver(tsc_driver); - -MODULE_AUTHOR("Cyril Chemparathy"); -MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); -MODULE_ALIAS("platform:tnetv107x-ts"); -MODULE_LICENSE("GPL"); |