1f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/* 2f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Samsung S3C24XX touchscreen driver 3f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 4f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * This program is free software; you can redistribute it and/or modify 5f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * it under the term of the GNU General Public License as published by 6f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * the Free Software Foundation; either version 2 of the License, or 7f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * (at your option) any later version. 8f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 9f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * This program is distributed in the hope that it will be useful, 10f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * GNU General Public License for more details. 13f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 14f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * You should have received a copy of the GNU General Public License 15f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * along with this program; if not, write to the Free Software 16f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 18f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Copyright 2004 Arnaud Patard <arnaud.patard@rtp-net.org> 19f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Copyright 2008 Ben Dooks <ben-linux@fluff.org> 20f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Copyright 2009 Simtec Electronics <linux@simtec.co.uk> 21f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 22f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Additional work by Herbert Pötzl <herbert@13thfloor.at> and 23f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Harald Welte <laforge@openmoko.org> 24f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 25f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 26f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/errno.h> 27f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/kernel.h> 28f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/module.h> 29f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/gpio.h> 30f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/input.h> 31f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/init.h> 32f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/delay.h> 33f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/interrupt.h> 34f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/platform_device.h> 35f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/clk.h> 36f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <linux/io.h> 37f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 38f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <plat/adc.h> 39f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#include <plat/regs-adc.h> 4073e59b1d6b69f5ae02e3be5e2b3259c46d8bb27aMaurus Cuelenaere#include <plat/ts.h> 41f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 42f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) 43f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 44f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#define INT_DOWN (0) 45f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#define INT_UP (1 << 8) 46f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 47f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#define WAIT4INT (S3C2410_ADCTSC_YM_SEN | \ 48f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_YP_SEN | \ 49f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_XP_SEN | \ 50f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_XY_PST(3)) 51f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 52f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#define AUTOPST (S3C2410_ADCTSC_YM_SEN | \ 53f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_YP_SEN | \ 54f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_XP_SEN | \ 55f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_AUTO_PST | \ 56f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard S3C2410_ADCTSC_XY_PST(0)) 57f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 5891df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna#define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */ 5991df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna 60f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/* Per-touchscreen data. */ 61f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 62f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 63f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * struct s3c2410ts - driver touchscreen state. 64f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @client: The ADC client we registered with the core driver. 65f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @dev: The device we are bound to. 66f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @input: The input device we registered with the input subsystem. 67f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @clock: The clock for the adc. 68f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @io: Pointer to the IO base. 69f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @xp: The accumulated X position data. 70f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @yp: The accumulated Y position data. 71f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @irq_tc: The interrupt number for pen up/down interrupt 72f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @count: The number of samples collected. 73f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @shift: The log2 of the maximum count to read in one go. 7491df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna * @features: The features supported by the TSADC MOdule. 75f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 76f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstruct s3c2410ts { 77f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct s3c_adc_client *client; 78f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct device *dev; 79f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct input_dev *input; 80f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct clk *clock; 81f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard void __iomem *io; 82f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long xp; 83f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long yp; 84f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard int irq_tc; 85f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard int count; 86f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard int shift; 8791df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna int features; 88f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard}; 89f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 90f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic struct s3c2410ts ts; 91f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 92f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 93f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * get_down - return the down state of the pen 94f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @data0: The data read from ADCDAT0 register. 95f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @data1: The data read from ADCDAT1 register. 96f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 97f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Return non-zero if both readings show that the pen is down. 98f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 99f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic inline bool get_down(unsigned long data0, unsigned long data1) 100f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 101f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* returns true if both data values show stylus down */ 102f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return (!(data0 & S3C2410_ADCDAT0_UPDOWN) && 103f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard !(data1 & S3C2410_ADCDAT0_UPDOWN)); 104f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 105f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 106f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic void touch_timer_fire(unsigned long data) 107f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 108f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long data0; 109f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long data1; 110f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard bool down; 111f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 112f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard data0 = readl(ts.io + S3C2410_ADCDAT0); 113f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard data1 = readl(ts.io + S3C2410_ADCDAT1); 114f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 115f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard down = get_down(data0, data1); 116f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 11723c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick if (down) { 11823c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick if (ts.count == (1 << ts.shift)) { 11923c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.xp >>= ts.shift; 12023c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.yp >>= ts.shift; 121f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 12223c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n", 12323c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick __func__, ts.xp, ts.yp, ts.count); 124f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 12523c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick input_report_abs(ts.input, ABS_X, ts.xp); 12623c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick input_report_abs(ts.input, ABS_Y, ts.yp); 127f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 12823c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick input_report_key(ts.input, BTN_TOUCH, 1); 12923c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick input_sync(ts.input); 130f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 13123c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.xp = 0; 13223c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.yp = 0; 13323c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.count = 0; 13423c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick } 135f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 136f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard s3c_adc_start(ts.client, 0, 1 << ts.shift); 137f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } else { 13823c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.xp = 0; 13923c239be223d7427da51656d6f196bde965d9796Vasily Khoruzhick ts.yp = 0; 140f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.count = 0; 141f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 142f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_report_key(ts.input, BTN_TOUCH, 0); 143f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_sync(ts.input); 144f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 145f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); 146f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 147f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 148f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 149f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic DEFINE_TIMER(touch_timer, touch_timer_fire, 0, 0); 150f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 151f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 152f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * stylus_irq - touchscreen stylus event interrupt 153f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @irq: The interrupt number 154f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @dev_id: The device ID. 155f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 156f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Called when the IRQ_TC is fired for a pen up or down event. 157f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 158f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic irqreturn_t stylus_irq(int irq, void *dev_id) 159f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 160f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long data0; 161f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned long data1; 162f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard bool down; 163f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 164f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard data0 = readl(ts.io + S3C2410_ADCDAT0); 165f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard data1 = readl(ts.io + S3C2410_ADCDAT1); 166f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 167f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard down = get_down(data0, data1); 168f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 169f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* TODO we should never get an interrupt with down set while 170f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * the timer is running, but maybe we ought to verify that the 171f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * timer isn't running anyways. */ 172f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 173f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (down) 174f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard s3c_adc_start(ts.client, 0, 1 << ts.shift); 175f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard else 176fbf89f25fc4dc68ba0857aca87e70fa5d2592d81Mark Brown dev_dbg(ts.dev, "%s: count=%d\n", __func__, ts.count); 177f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 17891df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna if (ts.features & FEAT_PEN_IRQ) { 17991df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna /* Clear pen down/up interrupt */ 18091df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP); 18191df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna } 18291df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna 183f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return IRQ_HANDLED; 184f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 185f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 186f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 187f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * s3c24xx_ts_conversion - ADC conversion callback 188f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @client: The client that was registered with the ADC core. 189f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @data0: The reading from ADCDAT0. 190f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @data1: The reading from ADCDAT1. 191f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @left: The number of samples left. 192f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 193f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Called when a conversion has finished. 194f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 195f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic void s3c24xx_ts_conversion(struct s3c_adc_client *client, 196f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned data0, unsigned data1, 197f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard unsigned *left) 198f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 199f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_dbg(ts.dev, "%s: %d,%d\n", __func__, data0, data1); 200f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 201f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.xp += data0; 202f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.yp += data1; 203f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 204f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.count++; 205f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 206f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* From tests, it seems that it is unlikely to get a pen-up 207f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * event during the conversion process which means we can 208f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * ignore any pen-up events with less than the requisite 209f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * count done. 210f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 211f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * In several thousand conversions, no pen-ups where detected 212f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * before count completed. 213f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 214f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 215f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 216f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 217f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * s3c24xx_ts_select - ADC selection callback. 218f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @client: The client that was registered with the ADC core. 219f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @select: The reason for select. 220f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 221f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Called when the ADC core selects (or deslects) us as a client. 222f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 223f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select) 224f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 225f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (select) { 226f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, 227f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.io + S3C2410_ADCTSC); 228f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } else { 229f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard mod_timer(&touch_timer, jiffies+1); 230f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(WAIT4INT | INT_UP, ts.io + S3C2410_ADCTSC); 231f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 232f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 233f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 234f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 235f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * s3c2410ts_probe - device core probe entry point 236f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @pdev: The device we are being bound to. 237f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 238f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Initialise, find and allocate any resources we need to run and then 239f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * register with the ADC and input systems. 240f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 241f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic int __devinit s3c2410ts_probe(struct platform_device *pdev) 242f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 243f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct s3c2410_ts_mach_info *info; 244f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct device *dev = &pdev->dev; 245f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct input_dev *input_dev; 246f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct resource *res; 247f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard int ret = -EINVAL; 248f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 249f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* Initialise input stuff */ 250f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard memset(&ts, 0, sizeof(struct s3c2410ts)); 251f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 252f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.dev = dev; 253f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 254f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard info = pdev->dev.platform_data; 255f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (!info) { 256f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "no platform data, cannot attach\n"); 257f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return -EINVAL; 258f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 259f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 260f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_dbg(dev, "initialising touchscreen\n"); 261f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 262f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.clock = clk_get(dev, "adc"); 263f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (IS_ERR(ts.clock)) { 264f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "cannot get adc clock source\n"); 265f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return -ENOENT; 266f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 267f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 268f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_enable(ts.clock); 269f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_dbg(dev, "got and enabled clocks\n"); 270f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 271f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.irq_tc = ret = platform_get_irq(pdev, 0); 272f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (ret < 0) { 273f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "no resource for interrupt\n"); 274f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_clk; 275f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 276f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 277f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 278f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (!res) { 279f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "no resource for registers\n"); 280f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = -ENOENT; 281f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_clk; 282f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 283f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 284f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.io = ioremap(res->start, resource_size(res)); 285f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (ts.io == NULL) { 286f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "cannot map registers\n"); 287f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = -ENOMEM; 288f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_clk; 289f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 290f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 291658ad39ea91d8f0597654032a768930497161a58Naveen Krishna /* inititalise the gpio */ 292658ad39ea91d8f0597654032a768930497161a58Naveen Krishna if (info->cfg_gpio) 293658ad39ea91d8f0597654032a768930497161a58Naveen Krishna info->cfg_gpio(to_platform_device(ts.dev)); 294f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 295f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, 296f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard s3c24xx_ts_conversion, 1); 297f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (IS_ERR(ts.client)) { 298f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "failed to register adc client\n"); 299f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = PTR_ERR(ts.client); 300f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_iomap; 301f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 302f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 303f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* Initialise registers */ 304f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if ((info->delay & 0xffff) > 0) 305f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); 306f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 307f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); 308f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 309f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_dev = input_allocate_device(); 310f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (!input_dev) { 311f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "Unable to allocate the input device !!\n"); 312f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = -ENOMEM; 313f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_iomap; 314f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 315f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 316f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input = input_dev; 317f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 318f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 319f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0); 320f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0); 321f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 322f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->name = "S3C24XX TouchScreen"; 323f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->id.bustype = BUS_HOST; 324f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->id.vendor = 0xDEAD; 325f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->id.product = 0xBEEF; 326f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.input->id.version = 0x0102; 327f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 328f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ts.shift = info->oversampling_shift; 32991df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna ts.features = platform_get_device_id(pdev)->driver_data; 330f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 331ec4665c46b11f6e444911ba73dddae6044dec909Yong Zhang ret = request_irq(ts.irq_tc, stylus_irq, 0, 332f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard "s3c2410_ts_pen", ts.input); 333f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (ret) { 334f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "cannot get TC interrupt\n"); 335f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_inputdev; 336f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 337f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 338f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_info(dev, "driver attached, registering input device\n"); 339f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 340f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* All went ok, so register to the input system */ 341f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = input_register_device(ts.input); 342f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if (ret < 0) { 343f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard dev_err(dev, "failed to register input device\n"); 344f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard ret = -EIO; 345f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard goto err_tcirq; 346f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard } 347f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 348f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return 0; 349f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 350f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard err_tcirq: 351f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard free_irq(ts.irq_tc, ts.input); 352f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard err_inputdev: 353ec1496b39576a3374e5461caac17b83b3275dbb7Axel Lin input_free_device(ts.input); 354f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard err_iomap: 355f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard iounmap(ts.io); 356f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard err_clk: 357f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard del_timer_sync(&touch_timer); 358f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_put(ts.clock); 359f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return ret; 360f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 361f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 362f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard/** 363f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * s3c2410ts_remove - device core removal entry point 364f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * @pdev: The device we are being removed from. 365f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * 366f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard * Free up our state ready to be removed. 367f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard */ 368f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic int __devexit s3c2410ts_remove(struct platform_device *pdev) 369f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 370f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard free_irq(ts.irq_tc, ts.input); 371f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard del_timer_sync(&touch_timer); 372f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 373f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_disable(ts.clock); 374f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_put(ts.clock); 375f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 376f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard input_unregister_device(ts.input); 377f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard iounmap(ts.io); 378f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 379f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return 0; 380f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 381f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 382f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#ifdef CONFIG_PM 383f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic int s3c2410ts_suspend(struct device *dev) 384f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 385f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC); 386f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard disable_irq(ts.irq_tc); 387f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_disable(ts.clock); 388f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 389f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return 0; 390f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 391f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 392f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic int s3c2410ts_resume(struct device *dev) 393f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard{ 394f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct platform_device *pdev = to_platform_device(dev); 395f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; 396f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 397f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard clk_enable(ts.clock); 3982f09586557ed9b6d50bc8bb5104e70006513bdc2Vasily Khoruzhick enable_irq(ts.irq_tc); 399f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 400f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard /* Initialise registers */ 401f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard if ((info->delay & 0xffff) > 0) 402f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); 403f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 404f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); 405f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 406f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard return 0; 407f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard} 408f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 409f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic struct dev_pm_ops s3c_ts_pmops = { 410f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .suspend = s3c2410ts_suspend, 411f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .resume = s3c2410ts_resume, 412f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard}; 413f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#endif 414f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 415f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic struct platform_device_id s3cts_driver_ids[] = { 41603a3f695cb9776cfa7da5e8e6d34fd20dd56510eVasily Khoruzhick { "s3c2410-ts", 0 }, 41703a3f695cb9776cfa7da5e8e6d34fd20dd56510eVasily Khoruzhick { "s3c2440-ts", 0 }, 41891df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna { "s3c64xx-ts", FEAT_PEN_IRQ }, 419f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard { } 420f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard}; 421f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud PatardMODULE_DEVICE_TABLE(platform, s3cts_driver_ids); 422f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 423f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patardstatic struct platform_driver s3c_ts_driver = { 424f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .driver = { 42591df77d7b550d3c8167c97c6e3b97f2ca4d9f3afNaveen Krishna .name = "samsung-ts", 426f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .owner = THIS_MODULE, 427f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#ifdef CONFIG_PM 428f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .pm = &s3c_ts_pmops, 429f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard#endif 430f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard }, 431f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .id_table = s3cts_driver_ids, 432f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .probe = s3c2410ts_probe, 433f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard .remove = __devexit_p(s3c2410ts_remove), 434f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard}; 435cdcc96e261909eccf596c070116c8b906a42b328JJ Dingmodule_platform_driver(s3c_ts_driver); 436f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard 437f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud PatardMODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " 438f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard "Ben Dooks <ben@simtec.co.uk>, " 439f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud Patard "Simtec Electronics <linux@simtec.co.uk>"); 440f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud PatardMODULE_DESCRIPTION("S3C24XX Touchscreen driver"); 441f5f96b93e745dd054110d511779e7ec5cfdfdfe6Arnaud PatardMODULE_LICENSE("GPL v2"); 442