Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Samsung S3C24XX touchscreen driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright 2008 Ben Dooks <ben-linux@fluff.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright 2009 Simtec Electronics <linux@simtec.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Additional work by Herbert Pötzl <herbert@13thfloor.at> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Harald Welte <laforge@openmoko.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/soc/samsung/s3c-adc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/platform_data/touchscreen-s3c2410.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define	S3C2410_ADCCON			(0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define	S3C2410_ADCTSC			(0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define	S3C2410_ADCDLY			(0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define	S3C2410_ADCDAT0			(0x0C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define	S3C2410_ADCDAT1			(0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define	S3C64XX_ADCUPDN			(0x14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define	S3C2443_ADCMUX			(0x18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define	S3C64XX_ADCCLRINT		(0x18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define	S5P_ADCMUX			(0x1C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define	S3C64XX_ADCCLRINTPNDNUP		(0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /* ADCTSC Register Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define S3C2443_ADCTSC_UD_SEN		(1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define S3C2410_ADCTSC_YM_SEN		(1<<7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define S3C2410_ADCTSC_YP_SEN		(1<<6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define S3C2410_ADCTSC_XM_SEN		(1<<5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define S3C2410_ADCTSC_XP_SEN		(1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define S3C2410_ADCTSC_AUTO_PST		(1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define S3C2410_ADCTSC_XY_PST(x)	(((x)&0x3)<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /* ADCDAT0 Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define S3C2410_ADCDAT0_UPDOWN		(1<<15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define S3C2410_ADCDAT0_AUTO_PST	(1<<14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define S3C2410_ADCDAT0_XY_PST		(0x3<<12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define S3C2410_ADCDAT0_XPDATA_MASK	(0x03FF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /* ADCDAT1 Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define S3C2410_ADCDAT1_UPDOWN		(1<<15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define S3C2410_ADCDAT1_AUTO_PST	(1<<14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define S3C2410_ADCDAT1_XY_PST		(0x3<<12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define S3C2410_ADCDAT1_YPDATA_MASK	(0x03FF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define TSC_SLEEP  (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define INT_DOWN	(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define INT_UP		(1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define WAIT4INT	(S3C2410_ADCTSC_YM_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			 S3C2410_ADCTSC_YP_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 			 S3C2410_ADCTSC_XP_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			 S3C2410_ADCTSC_XY_PST(3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define AUTOPST		(S3C2410_ADCTSC_YM_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			 S3C2410_ADCTSC_YP_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			 S3C2410_ADCTSC_XP_SEN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			 S3C2410_ADCTSC_AUTO_PST | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			 S3C2410_ADCTSC_XY_PST(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #define FEAT_PEN_IRQ	(1 << 0)	/* HAS ADCCLRINTPNDNUP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /* Per-touchscreen data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * struct s3c2410ts - driver touchscreen state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @client: The ADC client we registered with the core driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @dev: The device we are bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @input: The input device we registered with the input subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * @clock: The clock for the adc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * @io: Pointer to the IO base.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * @xp: The accumulated X position data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * @yp: The accumulated Y position data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * @irq_tc: The interrupt number for pen up/down interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * @count: The number of samples collected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * @shift: The log2 of the maximum count to read in one go.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * @features: The features supported by the TSADC MOdule.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) struct s3c2410ts {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	struct s3c_adc_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct clk *clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	void __iomem *io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	unsigned long xp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	unsigned long yp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	int irq_tc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	int features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static struct s3c2410ts ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * get_down - return the down state of the pen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @data0: The data read from ADCDAT0 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * @data1: The data read from ADCDAT1 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * Return non-zero if both readings show that the pen is down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline bool get_down(unsigned long data0, unsigned long data1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/* returns true if both data values show stylus down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	return (!(data0 & S3C2410_ADCDAT0_UPDOWN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		!(data1 & S3C2410_ADCDAT0_UPDOWN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void touch_timer_fire(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	unsigned long data0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	unsigned long data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	bool down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	data0 = readl(ts.io + S3C2410_ADCDAT0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	data1 = readl(ts.io + S3C2410_ADCDAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	down = get_down(data0, data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (down) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		if (ts.count == (1 << ts.shift)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			ts.xp >>= ts.shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			ts.yp >>= ts.shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 				__func__, ts.xp, ts.yp, ts.count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			input_report_abs(ts.input, ABS_X, ts.xp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			input_report_abs(ts.input, ABS_Y, ts.yp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			input_report_key(ts.input, BTN_TOUCH, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			input_sync(ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			ts.xp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			ts.yp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			ts.count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		s3c_adc_start(ts.client, 0, 1 << ts.shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		ts.xp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		ts.yp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		ts.count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		input_report_key(ts.input, BTN_TOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		input_sync(ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static DEFINE_TIMER(touch_timer, touch_timer_fire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * stylus_irq - touchscreen stylus event interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  * @irq: The interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  * @dev_id: The device ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * Called when the IRQ_TC is fired for a pen up or down event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static irqreturn_t stylus_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	unsigned long data0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	unsigned long data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	bool down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	data0 = readl(ts.io + S3C2410_ADCDAT0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	data1 = readl(ts.io + S3C2410_ADCDAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	down = get_down(data0, data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	/* TODO we should never get an interrupt with down set while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	 * the timer is running, but maybe we ought to verify that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	 * timer isn't running anyways. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		s3c_adc_start(ts.client, 0, 1 << ts.shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		dev_dbg(ts.dev, "%s: count=%d\n", __func__, ts.count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (ts.features & FEAT_PEN_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		/* Clear pen down/up interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * s3c24xx_ts_conversion - ADC conversion callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * @client: The client that was registered with the ADC core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  * @data0: The reading from ADCDAT0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  * @data1: The reading from ADCDAT1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * @left: The number of samples left.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * Called when a conversion has finished.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void s3c24xx_ts_conversion(struct s3c_adc_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				  unsigned data0, unsigned data1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 				  unsigned *left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	dev_dbg(ts.dev, "%s: %d,%d\n", __func__, data0, data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	ts.xp += data0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	ts.yp += data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	ts.count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	/* From tests, it seems that it is unlikely to get a pen-up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	 * event during the conversion process which means we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	 * ignore any pen-up events with less than the requisite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	 * count done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	 * In several thousand conversions, no pen-ups where detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	 * before count completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * s3c24xx_ts_select - ADC selection callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * @client: The client that was registered with the ADC core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * @select: The reason for select.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * Called when the ADC core selects (or deslects) us as a client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (select) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		       ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		mod_timer(&touch_timer, jiffies+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		writel(WAIT4INT | INT_UP, ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * s3c2410ts_probe - device core probe entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * @pdev: The device we are being bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * Initialise, find and allocate any resources we need to run and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * register with the ADC and input systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int s3c2410ts_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	struct s3c2410_ts_mach_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	/* Initialise input stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	memset(&ts, 0, sizeof(struct s3c2410ts));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	ts.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	info = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		dev_err(dev, "no platform data, cannot attach\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	dev_dbg(dev, "initialising touchscreen\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	ts.clock = clk_get(dev, "adc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	if (IS_ERR(ts.clock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		dev_err(dev, "cannot get adc clock source\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	ret = clk_prepare_enable(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		dev_err(dev, "Failed! to enabled clocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		goto err_clk_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	dev_dbg(dev, "got and enabled clocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	ts.irq_tc = ret = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		dev_err(dev, "no resource for interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		goto err_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		dev_err(dev, "no resource for registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		goto err_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	ts.io = ioremap(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (ts.io == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		dev_err(dev, "cannot map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		goto err_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	/* inititalise the gpio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	if (info->cfg_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		info->cfg_gpio(to_platform_device(ts.dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	ts.client = s3c_adc_register(pdev, s3c24xx_ts_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 				     s3c24xx_ts_conversion, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (IS_ERR(ts.client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		dev_err(dev, "failed to register adc client\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		ret = PTR_ERR(ts.client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		goto err_iomap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	/* Initialise registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	if ((info->delay & 0xffff) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (!input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		dev_err(dev, "Unable to allocate the input device !!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		goto err_iomap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	ts.input = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	ts.input->name = "S3C24XX TouchScreen";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	ts.input->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	ts.input->id.vendor = 0xDEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	ts.input->id.product = 0xBEEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	ts.input->id.version = 0x0102;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	ts.shift = info->oversampling_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	ts.features = platform_get_device_id(pdev)->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	ret = request_irq(ts.irq_tc, stylus_irq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			  "s3c2410_ts_pen", ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		dev_err(dev, "cannot get TC interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		goto err_inputdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	dev_info(dev, "driver attached, registering input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	/* All went ok, so register to the input system */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	ret = input_register_device(ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		dev_err(dev, "failed to register input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		goto err_tcirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  err_tcirq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	free_irq(ts.irq_tc, ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  err_inputdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	input_free_device(ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  err_iomap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	iounmap(ts.io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  err_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	clk_disable_unprepare(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	del_timer_sync(&touch_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)  err_clk_get:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	clk_put(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)  * s3c2410ts_remove - device core removal entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)  * @pdev: The device we are being removed from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)  * Free up our state ready to be removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int s3c2410ts_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	free_irq(ts.irq_tc, ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	del_timer_sync(&touch_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	clk_disable_unprepare(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	clk_put(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	input_unregister_device(ts.input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	iounmap(ts.io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int s3c2410ts_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	disable_irq(ts.irq_tc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	clk_disable(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int s3c2410ts_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	struct s3c2410_ts_mach_info *info = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	clk_enable(ts.clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	enable_irq(ts.irq_tc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	/* Initialise registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if ((info->delay & 0xffff) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static const struct dev_pm_ops s3c_ts_pmops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	.suspend	= s3c2410ts_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	.resume		= s3c2410ts_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static const struct platform_device_id s3cts_driver_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	{ "s3c2410-ts", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	{ "s3c2440-ts", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	{ "s3c64xx-ts", FEAT_PEN_IRQ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) MODULE_DEVICE_TABLE(platform, s3cts_driver_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static struct platform_driver s3c_ts_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	.driver         = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		.name   = "samsung-ts",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		.pm	= &s3c_ts_pmops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	.id_table	= s3cts_driver_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	.probe		= s3c2410ts_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	.remove		= s3c2410ts_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) module_platform_driver(s3c_ts_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	      "Ben Dooks <ben@simtec.co.uk>, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	      "Simtec Electronics <linux@simtec.co.uk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MODULE_DESCRIPTION("S3C24XX Touchscreen driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) MODULE_LICENSE("GPL v2");