xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/wm9705.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
6*4882a593Smuzhiyun  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7*4882a593Smuzhiyun  * Parts Copyright : Ian Molton <spyro@f2s.com>
8*4882a593Smuzhiyun  *                   Andrew Zabolotny <zap@homelink.ru>
9*4882a593Smuzhiyun  *                   Russell King <rmk@arm.linux.org.uk>
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/moduleparam.h>
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/input.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/bitops.h>
18*4882a593Smuzhiyun #include <linux/wm97xx.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define TS_NAME			"wm97xx"
21*4882a593Smuzhiyun #define WM9705_VERSION		"1.00"
22*4882a593Smuzhiyun #define DEFAULT_PRESSURE	0xb0c0
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun  * Module parameters
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * Set current used for pressure measurement.
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  * Set pil = 2 to use 400uA
32*4882a593Smuzhiyun  *     pil = 1 to use 200uA and
33*4882a593Smuzhiyun  *     pil = 0 to disable pressure measurement.
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * This is used to increase the range of values returned by the adc
36*4882a593Smuzhiyun  * when measureing touchpanel pressure.
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun static int pil;
39*4882a593Smuzhiyun module_param(pil, int, 0);
40*4882a593Smuzhiyun MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun  * Set threshold for pressure measurement.
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  * Pen down pressure below threshold is ignored.
46*4882a593Smuzhiyun  */
47*4882a593Smuzhiyun static int pressure = DEFAULT_PRESSURE & 0xfff;
48*4882a593Smuzhiyun module_param(pressure, int, 0);
49*4882a593Smuzhiyun MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun  * Set adc sample delay.
53*4882a593Smuzhiyun  *
54*4882a593Smuzhiyun  * For accurate touchpanel measurements, some settling time may be
55*4882a593Smuzhiyun  * required between the switch matrix applying a voltage across the
56*4882a593Smuzhiyun  * touchpanel plate and the ADC sampling the signal.
57*4882a593Smuzhiyun  *
58*4882a593Smuzhiyun  * This delay can be set by setting delay = n, where n is the array
59*4882a593Smuzhiyun  * position of the delay in the array delay_table below.
60*4882a593Smuzhiyun  * Long delays > 1ms are supported for completeness, but are not
61*4882a593Smuzhiyun  * recommended.
62*4882a593Smuzhiyun  */
63*4882a593Smuzhiyun static int delay = 4;
64*4882a593Smuzhiyun module_param(delay, int, 0);
65*4882a593Smuzhiyun MODULE_PARM_DESC(delay, "Set adc sample delay.");
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun  * Pen detect comparator threshold.
69*4882a593Smuzhiyun  *
70*4882a593Smuzhiyun  * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
71*4882a593Smuzhiyun  * i.e. 1 =  Vmid/15 threshold
72*4882a593Smuzhiyun  *      15 =  Vmid/1 threshold
73*4882a593Smuzhiyun  *
74*4882a593Smuzhiyun  * Adjust this value if you are having problems with pen detect not
75*4882a593Smuzhiyun  * detecting any down events.
76*4882a593Smuzhiyun  */
77*4882a593Smuzhiyun static int pdd = 8;
78*4882a593Smuzhiyun module_param(pdd, int, 0);
79*4882a593Smuzhiyun MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun  * Set adc mask function.
83*4882a593Smuzhiyun  *
84*4882a593Smuzhiyun  * Sources of glitch noise, such as signals driving an LCD display, may feed
85*4882a593Smuzhiyun  * through to the touch screen plates and affect measurement accuracy. In
86*4882a593Smuzhiyun  * order to minimise this, a signal may be applied to the MASK pin to delay or
87*4882a593Smuzhiyun  * synchronise the sampling.
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * 0 = No delay or sync
90*4882a593Smuzhiyun  * 1 = High on pin stops conversions
91*4882a593Smuzhiyun  * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
92*4882a593Smuzhiyun  * 3 = Edge triggered, edge on pin starts conversion after delay param
93*4882a593Smuzhiyun  */
94*4882a593Smuzhiyun static int mask;
95*4882a593Smuzhiyun module_param(mask, int, 0);
96*4882a593Smuzhiyun MODULE_PARM_DESC(mask, "Set adc mask function.");
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun  * ADC sample delay times in uS
100*4882a593Smuzhiyun  */
101*4882a593Smuzhiyun static const int delay_table[] = {
102*4882a593Smuzhiyun 	21,    /* 1 AC97 Link frames */
103*4882a593Smuzhiyun 	42,    /* 2                  */
104*4882a593Smuzhiyun 	84,    /* 4                  */
105*4882a593Smuzhiyun 	167,   /* 8                  */
106*4882a593Smuzhiyun 	333,   /* 16                 */
107*4882a593Smuzhiyun 	667,   /* 32                 */
108*4882a593Smuzhiyun 	1000,  /* 48                 */
109*4882a593Smuzhiyun 	1333,  /* 64                 */
110*4882a593Smuzhiyun 	2000,  /* 96                 */
111*4882a593Smuzhiyun 	2667,  /* 128                */
112*4882a593Smuzhiyun 	3333,  /* 160                */
113*4882a593Smuzhiyun 	4000,  /* 192                */
114*4882a593Smuzhiyun 	4667,  /* 224                */
115*4882a593Smuzhiyun 	5333,  /* 256                */
116*4882a593Smuzhiyun 	6000,  /* 288                */
117*4882a593Smuzhiyun 	0      /* No delay, switch matrix always on */
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun /*
121*4882a593Smuzhiyun  * Delay after issuing a POLL command.
122*4882a593Smuzhiyun  *
123*4882a593Smuzhiyun  * The delay is 3 AC97 link frames + the touchpanel settling delay
124*4882a593Smuzhiyun  */
poll_delay(int d)125*4882a593Smuzhiyun static inline void poll_delay(int d)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	udelay(3 * AC97_LINK_FRAME + delay_table[d]);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /*
131*4882a593Smuzhiyun  * set up the physical settings of the WM9705
132*4882a593Smuzhiyun  */
wm9705_phy_init(struct wm97xx * wm)133*4882a593Smuzhiyun static void wm9705_phy_init(struct wm97xx *wm)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	u16 dig1 = 0, dig2 = WM97XX_RPR;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/*
138*4882a593Smuzhiyun 	* mute VIDEO and AUX as they share X and Y touchscreen
139*4882a593Smuzhiyun 	* inputs on the WM9705
140*4882a593Smuzhiyun 	*/
141*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_AUX, 0x8000);
142*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/* touchpanel pressure current*/
145*4882a593Smuzhiyun 	if (pil == 2) {
146*4882a593Smuzhiyun 		dig2 |= WM9705_PIL;
147*4882a593Smuzhiyun 		dev_dbg(wm->dev,
148*4882a593Smuzhiyun 			"setting pressure measurement current to 400uA.");
149*4882a593Smuzhiyun 	} else if (pil)
150*4882a593Smuzhiyun 		dev_dbg(wm->dev,
151*4882a593Smuzhiyun 			"setting pressure measurement current to 200uA.");
152*4882a593Smuzhiyun 	if (!pil)
153*4882a593Smuzhiyun 		pressure = 0;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/* polling mode sample settling delay */
156*4882a593Smuzhiyun 	if (delay != 4) {
157*4882a593Smuzhiyun 		if (delay < 0 || delay > 15) {
158*4882a593Smuzhiyun 			dev_dbg(wm->dev, "supplied delay out of range.");
159*4882a593Smuzhiyun 			delay = 4;
160*4882a593Smuzhiyun 		}
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 	dig1 &= 0xff0f;
163*4882a593Smuzhiyun 	dig1 |= WM97XX_DELAY(delay);
164*4882a593Smuzhiyun 	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
165*4882a593Smuzhiyun 		delay_table[delay]);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* WM9705 pdd */
168*4882a593Smuzhiyun 	dig2 |= (pdd & 0x000f);
169*4882a593Smuzhiyun 	dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	/* mask */
172*4882a593Smuzhiyun 	dig2 |= ((mask & 0x3) << 4);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
175*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
wm9705_dig_enable(struct wm97xx * wm,int enable)178*4882a593Smuzhiyun static void wm9705_dig_enable(struct wm97xx *wm, int enable)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	if (enable) {
181*4882a593Smuzhiyun 		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
182*4882a593Smuzhiyun 				 wm->dig[2] | WM97XX_PRP_DET_DIG);
183*4882a593Smuzhiyun 		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
184*4882a593Smuzhiyun 	} else
185*4882a593Smuzhiyun 		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
186*4882a593Smuzhiyun 				 wm->dig[2] & ~WM97XX_PRP_DET_DIG);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
wm9705_aux_prepare(struct wm97xx * wm)189*4882a593Smuzhiyun static void wm9705_aux_prepare(struct wm97xx *wm)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
192*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
193*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
wm9705_dig_restore(struct wm97xx * wm)196*4882a593Smuzhiyun static void wm9705_dig_restore(struct wm97xx *wm)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
199*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
is_pden(struct wm97xx * wm)202*4882a593Smuzhiyun static inline int is_pden(struct wm97xx *wm)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	return wm->dig[2] & WM9705_PDEN;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun  * Read a sample from the WM9705 adc in polling mode.
209*4882a593Smuzhiyun  */
wm9705_poll_sample(struct wm97xx * wm,int adcsel,int * sample)210*4882a593Smuzhiyun static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	int timeout = 5 * delay;
213*4882a593Smuzhiyun 	bool wants_pen = adcsel & WM97XX_PEN_DOWN;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	if (wants_pen && !wm->pen_probably_down) {
216*4882a593Smuzhiyun 		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
217*4882a593Smuzhiyun 		if (!(data & WM97XX_PEN_DOWN))
218*4882a593Smuzhiyun 			return RC_PENUP;
219*4882a593Smuzhiyun 		wm->pen_probably_down = 1;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/* set up digitiser */
223*4882a593Smuzhiyun 	if (wm->mach_ops && wm->mach_ops->pre_sample)
224*4882a593Smuzhiyun 		wm->mach_ops->pre_sample(adcsel);
225*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
226*4882a593Smuzhiyun 				| WM97XX_POLL | WM97XX_DELAY(delay));
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	/* wait 3 AC97 time slots + delay for conversion */
229*4882a593Smuzhiyun 	poll_delay(delay);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	/* wait for POLL to go low */
232*4882a593Smuzhiyun 	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
233*4882a593Smuzhiyun 	       && timeout) {
234*4882a593Smuzhiyun 		udelay(AC97_LINK_FRAME);
235*4882a593Smuzhiyun 		timeout--;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (timeout == 0) {
239*4882a593Smuzhiyun 		/* If PDEN is set, we can get a timeout when pen goes up */
240*4882a593Smuzhiyun 		if (is_pden(wm))
241*4882a593Smuzhiyun 			wm->pen_probably_down = 0;
242*4882a593Smuzhiyun 		else
243*4882a593Smuzhiyun 			dev_dbg(wm->dev, "adc sample timeout");
244*4882a593Smuzhiyun 		return RC_PENUP;
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
248*4882a593Smuzhiyun 	if (wm->mach_ops && wm->mach_ops->post_sample)
249*4882a593Smuzhiyun 		wm->mach_ops->post_sample(adcsel);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* check we have correct sample */
252*4882a593Smuzhiyun 	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
253*4882a593Smuzhiyun 		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
254*4882a593Smuzhiyun 			adcsel & WM97XX_ADCSEL_MASK,
255*4882a593Smuzhiyun 			*sample & WM97XX_ADCSEL_MASK);
256*4882a593Smuzhiyun 		return RC_PENUP;
257*4882a593Smuzhiyun 	}
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
260*4882a593Smuzhiyun 		wm->pen_probably_down = 0;
261*4882a593Smuzhiyun 		return RC_PENUP;
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	return RC_VALID;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun  * Sample the WM9705 touchscreen in polling mode
269*4882a593Smuzhiyun  */
wm9705_poll_touch(struct wm97xx * wm,struct wm97xx_data * data)270*4882a593Smuzhiyun static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	int rc;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
275*4882a593Smuzhiyun 	if (rc != RC_VALID)
276*4882a593Smuzhiyun 		return rc;
277*4882a593Smuzhiyun 	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
278*4882a593Smuzhiyun 	if (rc != RC_VALID)
279*4882a593Smuzhiyun 		return rc;
280*4882a593Smuzhiyun 	if (pil) {
281*4882a593Smuzhiyun 		rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
282*4882a593Smuzhiyun 		if (rc != RC_VALID)
283*4882a593Smuzhiyun 			return rc;
284*4882a593Smuzhiyun 	} else
285*4882a593Smuzhiyun 		data->p = DEFAULT_PRESSURE;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	return RC_VALID;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun /*
291*4882a593Smuzhiyun  * Enable WM9705 continuous mode, i.e. touch data is streamed across
292*4882a593Smuzhiyun  * an AC97 slot
293*4882a593Smuzhiyun  */
wm9705_acc_enable(struct wm97xx * wm,int enable)294*4882a593Smuzhiyun static int wm9705_acc_enable(struct wm97xx *wm, int enable)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	u16 dig1, dig2;
297*4882a593Smuzhiyun 	int ret = 0;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	dig1 = wm->dig[1];
300*4882a593Smuzhiyun 	dig2 = wm->dig[2];
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (enable) {
303*4882a593Smuzhiyun 		/* continuous mode */
304*4882a593Smuzhiyun 		if (wm->mach_ops->acc_startup &&
305*4882a593Smuzhiyun 		    (ret = wm->mach_ops->acc_startup(wm)) < 0)
306*4882a593Smuzhiyun 			return ret;
307*4882a593Smuzhiyun 		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
308*4882a593Smuzhiyun 			  WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
309*4882a593Smuzhiyun 		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
310*4882a593Smuzhiyun 			WM97XX_DELAY(delay) |
311*4882a593Smuzhiyun 			WM97XX_SLT(wm->acc_slot) |
312*4882a593Smuzhiyun 			WM97XX_RATE(wm->acc_rate);
313*4882a593Smuzhiyun 		if (pil)
314*4882a593Smuzhiyun 			dig1 |= WM97XX_ADCSEL_PRES;
315*4882a593Smuzhiyun 		dig2 |= WM9705_PDEN;
316*4882a593Smuzhiyun 	} else {
317*4882a593Smuzhiyun 		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
318*4882a593Smuzhiyun 		dig2 &= ~WM9705_PDEN;
319*4882a593Smuzhiyun 		if (wm->mach_ops->acc_shutdown)
320*4882a593Smuzhiyun 			wm->mach_ops->acc_shutdown(wm);
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
324*4882a593Smuzhiyun 	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return ret;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun struct wm97xx_codec_drv wm9705_codec = {
330*4882a593Smuzhiyun 	.id = WM9705_ID2,
331*4882a593Smuzhiyun 	.name = "wm9705",
332*4882a593Smuzhiyun 	.poll_sample = wm9705_poll_sample,
333*4882a593Smuzhiyun 	.poll_touch = wm9705_poll_touch,
334*4882a593Smuzhiyun 	.acc_enable = wm9705_acc_enable,
335*4882a593Smuzhiyun 	.phy_init = wm9705_phy_init,
336*4882a593Smuzhiyun 	.dig_enable = wm9705_dig_enable,
337*4882a593Smuzhiyun 	.dig_restore = wm9705_dig_restore,
338*4882a593Smuzhiyun 	.aux_prepare = wm9705_aux_prepare,
339*4882a593Smuzhiyun };
340*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(wm9705_codec);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun /* Module information */
343*4882a593Smuzhiyun MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
344*4882a593Smuzhiyun MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
345*4882a593Smuzhiyun MODULE_LICENSE("GPL");
346