xref: /openbmc/linux/drivers/input/touchscreen/da9034-ts.c (revision 9bcc00b96fc14c0cca94252b19a6e05c7d031f4a)
1*9bcc00b9SEric Miao /*
2*9bcc00b9SEric Miao  * Touchscreen driver for Dialog Semiconductor DA9034
3*9bcc00b9SEric Miao  *
4*9bcc00b9SEric Miao  * Copyright (C) 2006-2008 Marvell International Ltd.
5*9bcc00b9SEric Miao  *	Fengwei Yin <fengwei.yin@marvell.com>
6*9bcc00b9SEric Miao  *	Eric Miao <eric.miao@marvell.com>
7*9bcc00b9SEric Miao  *
8*9bcc00b9SEric Miao  * This program is free software; you can redistribute it and/or modify
9*9bcc00b9SEric Miao  * it under the terms of the GNU General Public License version 2 as
10*9bcc00b9SEric Miao  * published by the Free Software Foundation.
11*9bcc00b9SEric Miao  */
12*9bcc00b9SEric Miao 
13*9bcc00b9SEric Miao #include <linux/module.h>
14*9bcc00b9SEric Miao #include <linux/kernel.h>
15*9bcc00b9SEric Miao #include <linux/init.h>
16*9bcc00b9SEric Miao #include <linux/delay.h>
17*9bcc00b9SEric Miao #include <linux/platform_device.h>
18*9bcc00b9SEric Miao #include <linux/input.h>
19*9bcc00b9SEric Miao #include <linux/mfd/da903x.h>
20*9bcc00b9SEric Miao 
21*9bcc00b9SEric Miao #define DA9034_MANUAL_CTRL	0x50
22*9bcc00b9SEric Miao #define DA9034_LDO_ADC_EN	(1 << 4)
23*9bcc00b9SEric Miao 
24*9bcc00b9SEric Miao #define DA9034_AUTO_CTRL1	0x51
25*9bcc00b9SEric Miao 
26*9bcc00b9SEric Miao #define DA9034_AUTO_CTRL2	0x52
27*9bcc00b9SEric Miao #define DA9034_AUTO_TSI_EN	(1 << 3)
28*9bcc00b9SEric Miao #define DA9034_PEN_DETECT	(1 << 4)
29*9bcc00b9SEric Miao 
30*9bcc00b9SEric Miao #define DA9034_TSI_CTRL1	0x53
31*9bcc00b9SEric Miao #define DA9034_TSI_CTRL2	0x54
32*9bcc00b9SEric Miao #define DA9034_TSI_X_MSB	0x6c
33*9bcc00b9SEric Miao #define DA9034_TSI_Y_MSB	0x6d
34*9bcc00b9SEric Miao #define DA9034_TSI_XY_LSB	0x6e
35*9bcc00b9SEric Miao 
36*9bcc00b9SEric Miao enum {
37*9bcc00b9SEric Miao 	STATE_IDLE,	/* wait for pendown */
38*9bcc00b9SEric Miao 	STATE_BUSY,	/* TSI busy sampling */
39*9bcc00b9SEric Miao 	STATE_STOP,	/* sample available */
40*9bcc00b9SEric Miao 	STATE_WAIT,	/* Wait to start next sample */
41*9bcc00b9SEric Miao };
42*9bcc00b9SEric Miao 
43*9bcc00b9SEric Miao enum {
44*9bcc00b9SEric Miao 	EVENT_PEN_DOWN,
45*9bcc00b9SEric Miao 	EVENT_PEN_UP,
46*9bcc00b9SEric Miao 	EVENT_TSI_READY,
47*9bcc00b9SEric Miao 	EVENT_TIMEDOUT,
48*9bcc00b9SEric Miao };
49*9bcc00b9SEric Miao 
50*9bcc00b9SEric Miao struct da9034_touch {
51*9bcc00b9SEric Miao 	struct device		*da9034_dev;
52*9bcc00b9SEric Miao 	struct input_dev	*input_dev;
53*9bcc00b9SEric Miao 
54*9bcc00b9SEric Miao 	struct delayed_work	tsi_work;
55*9bcc00b9SEric Miao 	struct notifier_block	notifier;
56*9bcc00b9SEric Miao 
57*9bcc00b9SEric Miao 	int	state;
58*9bcc00b9SEric Miao 
59*9bcc00b9SEric Miao 	int	interval_ms;
60*9bcc00b9SEric Miao 	int	x_inverted;
61*9bcc00b9SEric Miao 	int	y_inverted;
62*9bcc00b9SEric Miao 
63*9bcc00b9SEric Miao 	int	last_x;
64*9bcc00b9SEric Miao 	int	last_y;
65*9bcc00b9SEric Miao };
66*9bcc00b9SEric Miao 
67*9bcc00b9SEric Miao static inline int is_pen_down(struct da9034_touch *touch)
68*9bcc00b9SEric Miao {
69*9bcc00b9SEric Miao 	return da903x_query_status(touch->da9034_dev, DA9034_STATUS_PEN_DOWN);
70*9bcc00b9SEric Miao }
71*9bcc00b9SEric Miao 
72*9bcc00b9SEric Miao static inline int detect_pen_down(struct da9034_touch *touch, int on)
73*9bcc00b9SEric Miao {
74*9bcc00b9SEric Miao 	if (on)
75*9bcc00b9SEric Miao 		return da903x_set_bits(touch->da9034_dev,
76*9bcc00b9SEric Miao 				DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
77*9bcc00b9SEric Miao 	else
78*9bcc00b9SEric Miao 		return da903x_clr_bits(touch->da9034_dev,
79*9bcc00b9SEric Miao 				DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
80*9bcc00b9SEric Miao }
81*9bcc00b9SEric Miao 
82*9bcc00b9SEric Miao static int read_tsi(struct da9034_touch *touch)
83*9bcc00b9SEric Miao {
84*9bcc00b9SEric Miao 	uint8_t _x, _y, _v;
85*9bcc00b9SEric Miao 	int ret;
86*9bcc00b9SEric Miao 
87*9bcc00b9SEric Miao 	ret = da903x_read(touch->da9034_dev, DA9034_TSI_X_MSB, &_x);
88*9bcc00b9SEric Miao 	if (ret)
89*9bcc00b9SEric Miao 		return ret;
90*9bcc00b9SEric Miao 
91*9bcc00b9SEric Miao 	ret = da903x_read(touch->da9034_dev, DA9034_TSI_Y_MSB, &_y);
92*9bcc00b9SEric Miao 	if (ret)
93*9bcc00b9SEric Miao 		return ret;
94*9bcc00b9SEric Miao 
95*9bcc00b9SEric Miao 	ret = da903x_read(touch->da9034_dev, DA9034_TSI_XY_LSB, &_v);
96*9bcc00b9SEric Miao 	if (ret)
97*9bcc00b9SEric Miao 		return ret;
98*9bcc00b9SEric Miao 
99*9bcc00b9SEric Miao 	touch->last_x = ((_x << 2) & 0x3fc) | (_v & 0x3);
100*9bcc00b9SEric Miao 	touch->last_y = ((_y << 2) & 0x3fc) | ((_v & 0xc) >> 2);
101*9bcc00b9SEric Miao 
102*9bcc00b9SEric Miao 	return 0;
103*9bcc00b9SEric Miao }
104*9bcc00b9SEric Miao 
105*9bcc00b9SEric Miao static inline int start_tsi(struct da9034_touch *touch)
106*9bcc00b9SEric Miao {
107*9bcc00b9SEric Miao 	return da903x_set_bits(touch->da9034_dev,
108*9bcc00b9SEric Miao 			DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
109*9bcc00b9SEric Miao }
110*9bcc00b9SEric Miao 
111*9bcc00b9SEric Miao static inline int stop_tsi(struct da9034_touch *touch)
112*9bcc00b9SEric Miao {
113*9bcc00b9SEric Miao 	return da903x_clr_bits(touch->da9034_dev,
114*9bcc00b9SEric Miao 			DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
115*9bcc00b9SEric Miao }
116*9bcc00b9SEric Miao 
117*9bcc00b9SEric Miao static inline void report_pen_down(struct da9034_touch *touch)
118*9bcc00b9SEric Miao {
119*9bcc00b9SEric Miao 	int x = touch->last_x;
120*9bcc00b9SEric Miao 	int y = touch->last_y;
121*9bcc00b9SEric Miao 
122*9bcc00b9SEric Miao 	x &= 0xfff;
123*9bcc00b9SEric Miao 	if (touch->x_inverted)
124*9bcc00b9SEric Miao 		x = 1024 - x;
125*9bcc00b9SEric Miao 	y &= 0xfff;
126*9bcc00b9SEric Miao 	if (touch->y_inverted)
127*9bcc00b9SEric Miao 		y = 1024 - y;
128*9bcc00b9SEric Miao 
129*9bcc00b9SEric Miao 	input_report_abs(touch->input_dev, ABS_X, x);
130*9bcc00b9SEric Miao 	input_report_abs(touch->input_dev, ABS_Y, y);
131*9bcc00b9SEric Miao 	input_report_key(touch->input_dev, BTN_TOUCH, 1);
132*9bcc00b9SEric Miao 
133*9bcc00b9SEric Miao 	input_sync(touch->input_dev);
134*9bcc00b9SEric Miao }
135*9bcc00b9SEric Miao 
136*9bcc00b9SEric Miao static inline void report_pen_up(struct da9034_touch *touch)
137*9bcc00b9SEric Miao {
138*9bcc00b9SEric Miao 	input_report_key(touch->input_dev, BTN_TOUCH, 0);
139*9bcc00b9SEric Miao 	input_sync(touch->input_dev);
140*9bcc00b9SEric Miao }
141*9bcc00b9SEric Miao 
142*9bcc00b9SEric Miao static void da9034_event_handler(struct da9034_touch *touch, int event)
143*9bcc00b9SEric Miao {
144*9bcc00b9SEric Miao 	int err;
145*9bcc00b9SEric Miao 
146*9bcc00b9SEric Miao 	switch (touch->state) {
147*9bcc00b9SEric Miao 	case STATE_IDLE:
148*9bcc00b9SEric Miao 		if (event != EVENT_PEN_DOWN)
149*9bcc00b9SEric Miao 			break;
150*9bcc00b9SEric Miao 
151*9bcc00b9SEric Miao 		/* Enable auto measurement of the TSI, this will
152*9bcc00b9SEric Miao 		 * automatically disable pen down detection
153*9bcc00b9SEric Miao 		 */
154*9bcc00b9SEric Miao 		err = start_tsi(touch);
155*9bcc00b9SEric Miao 		if (err)
156*9bcc00b9SEric Miao 			goto err_reset;
157*9bcc00b9SEric Miao 
158*9bcc00b9SEric Miao 		touch->state = STATE_BUSY;
159*9bcc00b9SEric Miao 		break;
160*9bcc00b9SEric Miao 
161*9bcc00b9SEric Miao 	case STATE_BUSY:
162*9bcc00b9SEric Miao 		if (event != EVENT_TSI_READY)
163*9bcc00b9SEric Miao 			break;
164*9bcc00b9SEric Miao 
165*9bcc00b9SEric Miao 		err = read_tsi(touch);
166*9bcc00b9SEric Miao 		if (err)
167*9bcc00b9SEric Miao 			goto err_reset;
168*9bcc00b9SEric Miao 
169*9bcc00b9SEric Miao 		/* Disable auto measurement of the TSI, so that
170*9bcc00b9SEric Miao 		 * pen down status will be available
171*9bcc00b9SEric Miao 		 */
172*9bcc00b9SEric Miao 		err = stop_tsi(touch);
173*9bcc00b9SEric Miao 		if (err)
174*9bcc00b9SEric Miao 			goto err_reset;
175*9bcc00b9SEric Miao 
176*9bcc00b9SEric Miao 		touch->state = STATE_STOP;
177*9bcc00b9SEric Miao 		break;
178*9bcc00b9SEric Miao 
179*9bcc00b9SEric Miao 	case STATE_STOP:
180*9bcc00b9SEric Miao 		if (event == EVENT_PEN_DOWN) {
181*9bcc00b9SEric Miao 			report_pen_down(touch);
182*9bcc00b9SEric Miao 			schedule_delayed_work(&touch->tsi_work,
183*9bcc00b9SEric Miao 				msecs_to_jiffies(touch->interval_ms));
184*9bcc00b9SEric Miao 			touch->state = STATE_WAIT;
185*9bcc00b9SEric Miao 		}
186*9bcc00b9SEric Miao 
187*9bcc00b9SEric Miao 		if (event == EVENT_PEN_UP) {
188*9bcc00b9SEric Miao 			report_pen_up(touch);
189*9bcc00b9SEric Miao 			touch->state = STATE_IDLE;
190*9bcc00b9SEric Miao 		}
191*9bcc00b9SEric Miao 
192*9bcc00b9SEric Miao 		input_sync(touch->input_dev);
193*9bcc00b9SEric Miao 		break;
194*9bcc00b9SEric Miao 
195*9bcc00b9SEric Miao 	case STATE_WAIT:
196*9bcc00b9SEric Miao 		if (event != EVENT_TIMEDOUT)
197*9bcc00b9SEric Miao 			break;
198*9bcc00b9SEric Miao 
199*9bcc00b9SEric Miao 		if (is_pen_down(touch)) {
200*9bcc00b9SEric Miao 			start_tsi(touch);
201*9bcc00b9SEric Miao 			touch->state = STATE_BUSY;
202*9bcc00b9SEric Miao 		} else
203*9bcc00b9SEric Miao 			touch->state = STATE_IDLE;
204*9bcc00b9SEric Miao 		break;
205*9bcc00b9SEric Miao 	}
206*9bcc00b9SEric Miao 	return;
207*9bcc00b9SEric Miao 
208*9bcc00b9SEric Miao err_reset:
209*9bcc00b9SEric Miao 	touch->state = STATE_IDLE;
210*9bcc00b9SEric Miao 	stop_tsi(touch);
211*9bcc00b9SEric Miao 	detect_pen_down(touch, 1);
212*9bcc00b9SEric Miao }
213*9bcc00b9SEric Miao 
214*9bcc00b9SEric Miao static void da9034_tsi_work(struct work_struct *work)
215*9bcc00b9SEric Miao {
216*9bcc00b9SEric Miao 	struct da9034_touch *touch =
217*9bcc00b9SEric Miao 		container_of(work, struct da9034_touch, tsi_work.work);
218*9bcc00b9SEric Miao 
219*9bcc00b9SEric Miao 	da9034_event_handler(touch, EVENT_TIMEDOUT);
220*9bcc00b9SEric Miao }
221*9bcc00b9SEric Miao 
222*9bcc00b9SEric Miao static int da9034_touch_notifier(struct notifier_block *nb,
223*9bcc00b9SEric Miao 				 unsigned long event, void *data)
224*9bcc00b9SEric Miao {
225*9bcc00b9SEric Miao 	struct da9034_touch *touch =
226*9bcc00b9SEric Miao 		container_of(nb, struct da9034_touch, notifier);
227*9bcc00b9SEric Miao 
228*9bcc00b9SEric Miao 	if (event & DA9034_EVENT_PEN_DOWN) {
229*9bcc00b9SEric Miao 		if (is_pen_down(touch))
230*9bcc00b9SEric Miao 			da9034_event_handler(touch, EVENT_PEN_DOWN);
231*9bcc00b9SEric Miao 		else
232*9bcc00b9SEric Miao 			da9034_event_handler(touch, EVENT_PEN_UP);
233*9bcc00b9SEric Miao 	}
234*9bcc00b9SEric Miao 
235*9bcc00b9SEric Miao 	if (event & DA9034_EVENT_TSI_READY)
236*9bcc00b9SEric Miao 		da9034_event_handler(touch, EVENT_TSI_READY);
237*9bcc00b9SEric Miao 
238*9bcc00b9SEric Miao 	return 0;
239*9bcc00b9SEric Miao }
240*9bcc00b9SEric Miao 
241*9bcc00b9SEric Miao static int da9034_touch_open(struct input_dev *dev)
242*9bcc00b9SEric Miao {
243*9bcc00b9SEric Miao 	struct da9034_touch *touch = input_get_drvdata(dev);
244*9bcc00b9SEric Miao 	int ret;
245*9bcc00b9SEric Miao 
246*9bcc00b9SEric Miao 	ret = da903x_register_notifier(touch->da9034_dev, &touch->notifier,
247*9bcc00b9SEric Miao 			DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
248*9bcc00b9SEric Miao 	if (ret)
249*9bcc00b9SEric Miao 		return -EBUSY;
250*9bcc00b9SEric Miao 
251*9bcc00b9SEric Miao 	/* Enable ADC LDO */
252*9bcc00b9SEric Miao 	ret = da903x_set_bits(touch->da9034_dev,
253*9bcc00b9SEric Miao 			DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
254*9bcc00b9SEric Miao 	if (ret)
255*9bcc00b9SEric Miao 		return ret;
256*9bcc00b9SEric Miao 
257*9bcc00b9SEric Miao 	/* TSI_DELAY: 3 slots, TSI_SKIP: 3 slots */
258*9bcc00b9SEric Miao 	ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL1, 0x1b);
259*9bcc00b9SEric Miao 	if (ret)
260*9bcc00b9SEric Miao 		return ret;
261*9bcc00b9SEric Miao 
262*9bcc00b9SEric Miao 	ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL2, 0x00);
263*9bcc00b9SEric Miao 	if (ret)
264*9bcc00b9SEric Miao 		return ret;
265*9bcc00b9SEric Miao 
266*9bcc00b9SEric Miao 	touch->state = STATE_IDLE;
267*9bcc00b9SEric Miao 	detect_pen_down(touch, 1);
268*9bcc00b9SEric Miao 
269*9bcc00b9SEric Miao 	return 0;
270*9bcc00b9SEric Miao }
271*9bcc00b9SEric Miao 
272*9bcc00b9SEric Miao static void da9034_touch_close(struct input_dev *dev)
273*9bcc00b9SEric Miao {
274*9bcc00b9SEric Miao 	struct da9034_touch *touch = input_get_drvdata(dev);
275*9bcc00b9SEric Miao 
276*9bcc00b9SEric Miao 	da903x_unregister_notifier(touch->da9034_dev, &touch->notifier,
277*9bcc00b9SEric Miao 			DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
278*9bcc00b9SEric Miao 
279*9bcc00b9SEric Miao 	cancel_delayed_work_sync(&touch->tsi_work);
280*9bcc00b9SEric Miao 
281*9bcc00b9SEric Miao 	touch->state = STATE_IDLE;
282*9bcc00b9SEric Miao 	stop_tsi(touch);
283*9bcc00b9SEric Miao 	detect_pen_down(touch, 0);
284*9bcc00b9SEric Miao 
285*9bcc00b9SEric Miao 	/* Disable ADC LDO */
286*9bcc00b9SEric Miao 	da903x_clr_bits(touch->da9034_dev,
287*9bcc00b9SEric Miao 			DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
288*9bcc00b9SEric Miao }
289*9bcc00b9SEric Miao 
290*9bcc00b9SEric Miao 
291*9bcc00b9SEric Miao static int __devinit da9034_touch_probe(struct platform_device *pdev)
292*9bcc00b9SEric Miao {
293*9bcc00b9SEric Miao 	struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
294*9bcc00b9SEric Miao 	struct da9034_touch *touch;
295*9bcc00b9SEric Miao 	struct input_dev *input_dev;
296*9bcc00b9SEric Miao 	int ret;
297*9bcc00b9SEric Miao 
298*9bcc00b9SEric Miao 	touch = kzalloc(sizeof(struct da9034_touch), GFP_KERNEL);
299*9bcc00b9SEric Miao 	if (touch == NULL) {
300*9bcc00b9SEric Miao 		dev_err(&pdev->dev, "failed to allocate driver data\n");
301*9bcc00b9SEric Miao 		return -ENOMEM;
302*9bcc00b9SEric Miao 	}
303*9bcc00b9SEric Miao 
304*9bcc00b9SEric Miao 	touch->da9034_dev = pdev->dev.parent;
305*9bcc00b9SEric Miao 
306*9bcc00b9SEric Miao 	if (pdata) {
307*9bcc00b9SEric Miao 		touch->interval_ms	= pdata->interval_ms;
308*9bcc00b9SEric Miao 		touch->x_inverted	= pdata->x_inverted;
309*9bcc00b9SEric Miao 		touch->y_inverted	= pdata->y_inverted;
310*9bcc00b9SEric Miao 	} else
311*9bcc00b9SEric Miao 		/* fallback into default */
312*9bcc00b9SEric Miao 		touch->interval_ms	= 10;
313*9bcc00b9SEric Miao 
314*9bcc00b9SEric Miao 	INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work);
315*9bcc00b9SEric Miao 	touch->notifier.notifier_call = da9034_touch_notifier;
316*9bcc00b9SEric Miao 
317*9bcc00b9SEric Miao 	input_dev = input_allocate_device();
318*9bcc00b9SEric Miao 	if (!input_dev) {
319*9bcc00b9SEric Miao 		dev_err(&pdev->dev, "failed to allocate input device\n");
320*9bcc00b9SEric Miao 		ret = -ENOMEM;
321*9bcc00b9SEric Miao 		goto err_free_touch;
322*9bcc00b9SEric Miao 	}
323*9bcc00b9SEric Miao 
324*9bcc00b9SEric Miao 	input_dev->name		= pdev->name;
325*9bcc00b9SEric Miao 	input_dev->open		= da9034_touch_open;
326*9bcc00b9SEric Miao 	input_dev->close	= da9034_touch_close;
327*9bcc00b9SEric Miao 	input_dev->dev.parent	= &pdev->dev;
328*9bcc00b9SEric Miao 
329*9bcc00b9SEric Miao 	__set_bit(EV_ABS, input_dev->evbit);
330*9bcc00b9SEric Miao 	__set_bit(ABS_X, input_dev->absbit);
331*9bcc00b9SEric Miao 	__set_bit(ABS_Y, input_dev->absbit);
332*9bcc00b9SEric Miao 	input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
333*9bcc00b9SEric Miao 	input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
334*9bcc00b9SEric Miao 
335*9bcc00b9SEric Miao 	__set_bit(EV_KEY, input_dev->evbit);
336*9bcc00b9SEric Miao 	__set_bit(BTN_TOUCH, input_dev->keybit);
337*9bcc00b9SEric Miao 
338*9bcc00b9SEric Miao 	touch->input_dev = input_dev;
339*9bcc00b9SEric Miao 	input_set_drvdata(input_dev, touch);
340*9bcc00b9SEric Miao 
341*9bcc00b9SEric Miao 	ret = input_register_device(input_dev);
342*9bcc00b9SEric Miao 	if (ret)
343*9bcc00b9SEric Miao 		goto err_free_input;
344*9bcc00b9SEric Miao 
345*9bcc00b9SEric Miao 	platform_set_drvdata(pdev, touch);
346*9bcc00b9SEric Miao 	return 0;
347*9bcc00b9SEric Miao 
348*9bcc00b9SEric Miao err_free_input:
349*9bcc00b9SEric Miao 	input_free_device(input_dev);
350*9bcc00b9SEric Miao err_free_touch:
351*9bcc00b9SEric Miao 	kfree(touch);
352*9bcc00b9SEric Miao 	return ret;
353*9bcc00b9SEric Miao }
354*9bcc00b9SEric Miao 
355*9bcc00b9SEric Miao static int __devexit da9034_touch_remove(struct platform_device *pdev)
356*9bcc00b9SEric Miao {
357*9bcc00b9SEric Miao 	struct da9034_touch *touch = platform_get_drvdata(pdev);
358*9bcc00b9SEric Miao 
359*9bcc00b9SEric Miao 	input_unregister_device(touch->input_dev);
360*9bcc00b9SEric Miao 	kfree(touch);
361*9bcc00b9SEric Miao 
362*9bcc00b9SEric Miao 	return 0;
363*9bcc00b9SEric Miao }
364*9bcc00b9SEric Miao 
365*9bcc00b9SEric Miao static struct platform_driver da9034_touch_driver = {
366*9bcc00b9SEric Miao 	.driver	= {
367*9bcc00b9SEric Miao 		.name	= "da9034-touch",
368*9bcc00b9SEric Miao 		.owner	= THIS_MODULE,
369*9bcc00b9SEric Miao 	},
370*9bcc00b9SEric Miao 	.probe		= da9034_touch_probe,
371*9bcc00b9SEric Miao 	.remove		= __devexit_p(da9034_touch_remove),
372*9bcc00b9SEric Miao };
373*9bcc00b9SEric Miao 
374*9bcc00b9SEric Miao static int __init da9034_touch_init(void)
375*9bcc00b9SEric Miao {
376*9bcc00b9SEric Miao 	return platform_driver_register(&da9034_touch_driver);
377*9bcc00b9SEric Miao }
378*9bcc00b9SEric Miao module_init(da9034_touch_init);
379*9bcc00b9SEric Miao 
380*9bcc00b9SEric Miao static void __exit da9034_touch_exit(void)
381*9bcc00b9SEric Miao {
382*9bcc00b9SEric Miao 	platform_driver_unregister(&da9034_touch_driver);
383*9bcc00b9SEric Miao }
384*9bcc00b9SEric Miao module_exit(da9034_touch_exit);
385*9bcc00b9SEric Miao 
386*9bcc00b9SEric Miao MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
387*9bcc00b9SEric Miao MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
388*9bcc00b9SEric Miao MODULE_LICENSE("GPL");
389*9bcc00b9SEric Miao MODULE_ALIAS("platform:da9034-touch");
390