Staging: mrst-touchscreen - fix channel allocation
[firefly-linux-kernel-4.4.55.git] / drivers / staging / mrst-touchscreen / intel-mid-touch.c
1 /*
2  * Intel MID Resistive Touch Screen Driver
3  *
4  * Copyright (C) 2008 Intel Corp
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
22  *                          Ramesh Agarwal (ramesh.agarwal@intel.com)
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  *
25  * TODO:
26  *      review conversion of r/m/w sequences
27  */
28
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/input.h>
32 #include <linux/interrupt.h>
33 #include <linux/err.h>
34 #include <linux/param.h>
35 #include <linux/slab.h>
36 #include <linux/platform_device.h>
37 #include <linux/irq.h>
38 #include <linux/delay.h>
39 #include <asm/intel_scu_ipc.h>
40
41 /* PMIC Interrupt registers */
42 #define PMIC_REG_ID1            0x00 /* PMIC ID1 register */
43
44 /* PMIC Interrupt registers */
45 #define PMIC_REG_INT            0x04 /* PMIC interrupt register */
46 #define PMIC_REG_MINT           0x05 /* PMIC interrupt mask register */
47
48 /* ADC Interrupt registers */
49 #define PMIC_REG_ADCINT         0x5F /* ADC interrupt register */
50 #define PMIC_REG_MADCINT        0x60 /* ADC interrupt mask register */
51
52 /* ADC Control registers */
53 #define PMIC_REG_ADCCNTL1       0x61 /* ADC control register */
54
55 /* ADC Channel Selection registers */
56 #define PMICADDR0               0xA4
57 #define END_OF_CHANNEL          0x1F
58
59 /* ADC Result register */
60 #define PMIC_REG_ADCSNS0H       0x64
61
62 /* ADC channels for touch screen */
63 #define MRST_TS_CHAN10          0xA /* Touch screen X+ connection */
64 #define MRST_TS_CHAN11          0xB /* Touch screen X- connection */
65 #define MRST_TS_CHAN12          0xC /* Touch screen Y+ connection */
66 #define MRST_TS_CHAN13          0xD /* Touch screen Y- connection */
67
68 /* Touch screen channel BIAS constants */
69 #define MRST_XBIAS              0x20
70 #define MRST_YBIAS              0x40
71 #define MRST_ZBIAS              0x80
72
73 /* Touch screen coordinates */
74 #define MRST_X_MIN              10
75 #define MRST_X_MAX              1024
76 #define MRST_X_FUZZ             5
77 #define MRST_Y_MIN              10
78 #define MRST_Y_MAX              1024
79 #define MRST_Y_FUZZ             5
80 #define MRST_PRESSURE_MIN       0
81 #define MRST_PRESSURE_NOMINAL   50
82 #define MRST_PRESSURE_MAX       100
83
84 #define WAIT_ADC_COMPLETION     10 /* msec */
85
86 /* PMIC ADC round robin delays */
87 #define ADC_LOOP_DELAY0         0x0 /* Continuous loop */
88 #define ADC_LOOP_DELAY1         0x1 /* 4.5  ms approximate */
89
90 /* PMIC Vendor Identifiers */
91 #define PMIC_VENDOR_FS          0 /* PMIC vendor FreeScale */
92 #define PMIC_VENDOR_MAXIM       1 /* PMIC vendor MAXIM */
93 #define PMIC_VENDOR_NEC         2 /* PMIC vendor NEC */
94 #define MRSTOUCH_MAX_CHANNELS   32 /* Maximum ADC channels */
95
96 /* Touch screen device structure */
97 struct mrstouch_dev {
98         struct device *dev; /* device associated with touch screen */
99         struct input_dev *input;
100         char phys[32];
101         u16 asr;                /* Address selection register */
102         int irq;
103         unsigned int vendor;    /* PMIC vendor */
104         unsigned int rev;       /* PMIC revision */
105
106         int (*read_prepare)(struct mrstouch_dev *tsdev);
107         int (*read)(struct mrstouch_dev *tsdev, u16 *x, u16 *y, u16 *z);
108         int (*read_finish)(struct mrstouch_dev *tsdev);
109 };
110
111
112 /*************************** NEC and Maxim Interface ************************/
113
114 static int mrstouch_nec_adc_read_prepare(struct mrstouch_dev *tsdev)
115 {
116         u16 reg;
117         int err;
118
119         err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
120         if (err)
121                 return err;
122
123         reg &= 0xDFFF; /* Disable pendet */
124
125         /* Set MADCINT and update ADCCNTL1 (next reg byte) */
126         return intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
127 }
128
129 /*
130  * Enables PENDET interrupt.
131  */
132 static int mrstouch_nec_adc_read_finish(struct mrstouch_dev *tsdev)
133 {
134         u16 reg;
135         u8 r;
136         u8 pendet_enabled;
137         int retry = 0;
138         int err;
139
140         err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
141         if (err)
142                 return err;
143
144         reg &= ~0x0005;
145         reg |= 0x2000; /* Enable pendet */
146
147         /* Set MADCINT and update ADCCNTL1 (next reg byte) */
148         err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
149         if (err)
150                 return err;
151
152         /*
153          * Sometimes even after the register write succeeds
154          * the PMIC register value is not updated. Retry few iterations
155          * to enable pendet.
156          */
157         do {
158                 err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
159                 if (err)
160                         return err;
161
162                 pendet_enabled = (r >> 5) & 0x01;
163
164                 if (!pendet_enabled) {
165                         if (++retry >= 10) {
166                                 dev_err(tsdev->dev,
167                                         "Touch screen disabled.\n");
168                                 return -EIO;
169                         }
170
171                         msleep(10);
172
173                         err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1,
174                                                      reg >> 8);
175                         if (err)
176                                 return err;
177                 }
178         } while (!pendet_enabled);
179
180         return 0;
181 }
182
183 /*
184  * Reads PMIC ADC touch screen result
185  * Reads ADC storage registers for higher 7 and lower 3 bits and
186  * converts the two readings into a single value and turns off gain bit
187  */
188 static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
189 {
190         int err;
191         u16 result;
192         u32 res;
193
194         result = PMIC_REG_ADCSNS0H + offset;
195
196         if (chan == MRST_TS_CHAN12)
197                 result += 4;
198
199         err = intel_scu_ipc_ioread32(result, &res);
200         if (err)
201                 return err;
202
203         /* Mash the bits up */
204
205         *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
206         *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
207         *vp &= 0x3FF;
208
209         res >>= 16;
210
211         *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
212         *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
213         *vm &= 0x3FF;
214
215         return 0;
216 }
217
218 /*
219  * Enables X, Y and Z bias values
220  * Enables YPYM for X channels and XPXM for Y channels
221  */
222 static int mrstouch_ts_bias_set(uint offset, uint bias)
223 {
224         int count;
225         u16 chan, start;
226         u16 reg[4];
227         u8 data[4];
228
229         chan = PMICADDR0 + offset;
230         start = MRST_TS_CHAN10;
231
232         for (count = 0; count <= 3; count++) {
233                 reg[count] = chan++;
234                 data[count] = bias | (start + count);
235         }
236
237         return intel_scu_ipc_writev(reg, data, 4);
238 }
239
240 /* To read touch screen channel values */
241 static int mrstouch_nec_adc_read(struct mrstouch_dev *tsdev,
242                                  u16 *x, u16 *y, u16 *z)
243 {
244         int err;
245         u16 xm, ym, zm;
246
247         /* configure Y bias for X channels */
248         err = mrstouch_ts_bias_set(tsdev->asr, MRST_YBIAS);
249         if (err)
250                 goto ipc_error;
251
252         msleep(WAIT_ADC_COMPLETION);
253
254         /* read x+ and x- channels */
255         err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, x, &xm);
256         if (err)
257                 goto ipc_error;
258
259         /* configure x bias for y channels */
260         err = mrstouch_ts_bias_set(tsdev->asr, MRST_XBIAS);
261         if (err)
262                 goto ipc_error;
263
264         msleep(WAIT_ADC_COMPLETION);
265
266         /* read y+ and y- channels */
267         err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, y, &ym);
268         if (err)
269                 goto ipc_error;
270
271         /* configure z bias for x and y channels */
272         err = mrstouch_ts_bias_set(tsdev->asr, MRST_ZBIAS);
273         if (err)
274                 goto ipc_error;
275
276         msleep(WAIT_ADC_COMPLETION);
277
278         /* read z+ and z- channels */
279         err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, z, &zm);
280         if (err)
281                 goto ipc_error;
282
283         return 0;
284
285 ipc_error:
286         dev_err(tsdev->dev, "ipc error during adc read\n");
287         return err;
288 }
289
290
291 /*************************** Freescale Interface ************************/
292
293 static int mrstouch_fs_adc_read_prepare(struct mrstouch_dev *tsdev)
294 {
295         int err, count;
296         u16 chan;
297         u16 reg[5];
298         u8 data[5];
299
300         /* Stop the ADC */
301         err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
302         if (err)
303                 goto ipc_error;
304
305         chan = PMICADDR0 + tsdev->asr;
306
307         /* Set X BIAS */
308         for (count = 0; count <= 3; count++) {
309                 reg[count] = chan++;
310                 data[count] = 0x2A;
311         }
312         reg[count] =  chan++; /* Dummy */
313         data[count] = 0;
314
315         err = intel_scu_ipc_writev(reg, data, 5);
316         if (err)
317                 goto ipc_error;
318
319         msleep(WAIT_ADC_COMPLETION);
320
321         /* Set Y BIAS */
322         for (count = 0; count <= 3; count++) {
323                 reg[count] = chan++;
324                 data[count] = 0x4A;
325         }
326         reg[count] = chan++; /* Dummy */
327         data[count] = 0;
328
329         err = intel_scu_ipc_writev(reg, data, 5);
330         if (err)
331                 goto ipc_error;
332
333         msleep(WAIT_ADC_COMPLETION);
334
335         /* Set Z BIAS */
336         err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
337         if (err)
338                 goto ipc_error;
339
340         msleep(WAIT_ADC_COMPLETION);
341
342         return 0;
343
344 ipc_error:
345         dev_err(tsdev->dev, "ipc error during %s\n", __func__);
346         return err;
347 }
348
349 static int mrstouch_fs_adc_read(struct mrstouch_dev *tsdev,
350                                 u16 *x, u16 *y, u16 *z)
351 {
352         int err;
353         u16 result;
354         u16 reg[4];
355         u8 data[4];
356
357         result = PMIC_REG_ADCSNS0H + tsdev->asr;
358
359         reg[0] = result + 4;
360         reg[1] = result + 5;
361         reg[2] = result + 16;
362         reg[3] = result + 17;
363
364         err = intel_scu_ipc_readv(reg, data, 4);
365         if (err)
366                 goto ipc_error;
367
368         *x = data[0] << 3; /* Higher 7 bits */
369         *x |= data[1] & 0x7; /* Lower 3 bits */
370         *x &= 0x3FF;
371
372         *y = data[2] << 3; /* Higher 7 bits */
373         *y |= data[3] & 0x7; /* Lower 3 bits */
374         *y &= 0x3FF;
375
376         /* Read Z value */
377         reg[0] = result + 28;
378         reg[1] = result + 29;
379
380         err = intel_scu_ipc_readv(reg, data, 4);
381         if (err)
382                 goto ipc_error;
383
384         *z = data[0] << 3; /* Higher 7 bits */
385         *z |= data[1] & 0x7; /* Lower 3 bits */
386         *z &= 0x3FF;
387
388         return 0;
389
390 ipc_error:
391         dev_err(tsdev->dev, "ipc error during %s\n", __func__);
392         return err;
393 }
394
395 static int mrstouch_fs_adc_read_finish(struct mrstouch_dev *tsdev)
396 {
397         int err, count;
398         u16 chan;
399         u16 reg[5];
400         u8 data[5];
401
402         /* Clear all TS channels */
403         chan = PMICADDR0 + tsdev->asr;
404         for (count = 0; count <= 4; count++) {
405                 reg[count] = chan++;
406                 data[count] = 0;
407         }
408         err = intel_scu_ipc_writev(reg, data, 5);
409         if (err)
410                 goto ipc_error;
411
412         for (count = 0; count <= 4; count++) {
413                 reg[count] = chan++;
414                 data[count] = 0;
415         }
416         err = intel_scu_ipc_writev(reg, data, 5);
417         if (err)
418                 goto ipc_error;
419
420         err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
421         if (err)
422                 goto ipc_error;
423
424         /* Start ADC */
425         err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
426         if (err)
427                 goto ipc_error;
428
429         return 0;
430
431 ipc_error:
432         dev_err(tsdev->dev, "ipc error during %s\n", __func__);
433         return err;
434 }
435
436 static void mrstouch_report_event(struct input_dev *input,
437                         unsigned int x, unsigned int y, unsigned int z)
438 {
439         if (z > MRST_PRESSURE_NOMINAL) {
440                 /* Pen touched, report button touch and coordinates */
441                 input_report_key(input, BTN_TOUCH, 1);
442                 input_report_abs(input, ABS_X, x);
443                 input_report_abs(input, ABS_Y, y);
444         } else {
445                 input_report_key(input, BTN_TOUCH, 0);
446         }
447
448         input_report_abs(input, ABS_PRESSURE, z);
449         input_sync(input);
450 }
451
452 /* PENDET interrupt handler */
453 static irqreturn_t mrstouch_pendet_irq(int irq, void *dev_id)
454 {
455         struct mrstouch_dev *tsdev = dev_id;
456         u16 x, y, z;
457
458         /*
459          * Should we lower thread priority? Probably not, since we are
460          * not spinning but sleeping...
461          */
462
463         if (tsdev->read_prepare(tsdev))
464                 goto out;
465
466         do {
467                 if (tsdev->read(tsdev, &x, &y, &z))
468                         break;
469
470                 mrstouch_report_event(tsdev->input, x, y, z);
471         } while (z > MRST_PRESSURE_NOMINAL);
472
473         tsdev->read_finish(tsdev);
474
475 out:
476         return IRQ_HANDLED;
477 }
478
479 /* Utility to read PMIC ID */
480 static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
481 {
482         int err;
483         u8 r;
484
485         err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
486         if (err)
487                 return err;
488
489         *vendor = r & 0x7;
490         *rev = (r >> 3) & 0x7;
491
492         return 0;
493 }
494
495 /*
496  * Parse ADC channels to find end of the channel configured by other ADC user
497  * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
498  */
499 static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
500 {
501         int err, i, found;
502         u8 r8;
503
504         found = -1;
505
506         for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
507                 if (found >= 0)
508                         break;
509
510                 err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
511                 if (err)
512                         return err;
513
514                 if (r8 == END_OF_CHANNEL) {
515                         found = i;
516                         break;
517                 }
518         }
519         if (found < 0)
520                 return 0;
521
522         if (tsdev->vendor == PMIC_VENDOR_FS) {
523                 if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
524                         return -ENOSPC;
525         } else {
526                 if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
527                         return -ENOSPC;
528         }
529         return found;
530 }
531
532
533 /*
534  * Writes touch screen channels to ADC address selection registers
535  */
536 static int __devinit mrstouch_ts_chan_set(uint offset)
537 {
538         u16 chan;
539
540         int ret, count;
541
542         chan = PMICADDR0 + offset;
543         for (count = 0; count <= 3; count++) {
544                 ret = intel_scu_ipc_iowrite8(chan++, MRST_TS_CHAN10 + count);
545                 if (ret)
546                         return ret;
547         }
548         return intel_scu_ipc_iowrite8(chan++, END_OF_CHANNEL);
549 }
550
551 /* Initialize ADC */
552 static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
553 {
554         int err, start;
555         u8 ra, rm;
556
557         err = mrstouch_read_pmic_id(&tsdev->vendor, &tsdev->rev);
558         if (err) {
559                 dev_err(tsdev->dev, "Unable to read PMIC id\n");
560                 return err;
561         }
562
563         switch (tsdev->vendor) {
564         case PMIC_VENDOR_NEC:
565         case PMIC_VENDOR_MAXIM:
566                 tsdev->read_prepare = mrstouch_nec_adc_read_prepare;
567                 tsdev->read = mrstouch_nec_adc_read;
568                 tsdev->read_finish = mrstouch_nec_adc_read_finish;
569                 break;
570
571         case PMIC_VENDOR_FS:
572                 tsdev->read_prepare = mrstouch_fs_adc_read_prepare;
573                 tsdev->read = mrstouch_fs_adc_read;
574                 tsdev->read_finish = mrstouch_fs_adc_read_finish;
575                 break;
576
577         default:
578                 dev_err(tsdev->dev,
579                         "Unsupported touchscreen: %d\n", tsdev->vendor);
580                 return -ENXIO;
581         }
582
583         start = mrstouch_chan_parse(tsdev);
584         if (start < 0) {
585                 dev_err(tsdev->dev, "Unable to parse channels\n");
586                 return start;
587         }
588
589         tsdev->asr = start;
590
591         /*
592          * ADC power on, start, enable PENDET and set loop delay
593          * ADC loop delay is set to 4.5 ms approximately
594          * Loop delay more than this results in jitter in adc readings
595          * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
596          * interrupt generation sometimes.
597          */
598
599         if (tsdev->vendor == PMIC_VENDOR_FS) {
600                 ra = 0xE0 | ADC_LOOP_DELAY0;
601                 rm = 0x5;
602         } else {
603                 /* NEC and MAXIm not consistent with loop delay 0 */
604                 ra = 0xE0 | ADC_LOOP_DELAY1;
605                 rm = 0x0;
606
607                 /* configure touch screen channels */
608                 err = mrstouch_ts_chan_set(tsdev->asr);
609                 if (err)
610                         return err;
611         }
612
613         err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
614         if (err)
615                 return err;
616
617         err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
618         if (err)
619                 return err;
620
621         return 0;
622 }
623
624
625 /* Probe function for touch screen driver */
626 static int __devinit mrstouch_probe(struct platform_device *pdev)
627 {
628         struct mrstouch_dev *tsdev;
629         struct input_dev *input;
630         int err;
631         int irq;
632
633         irq = platform_get_irq(pdev, 0);
634         if (irq < 0) {
635                 dev_err(&pdev->dev, "no interrupt assigned\n");
636                 return -EINVAL;
637         }
638
639         tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
640         input = input_allocate_device();
641         if (!tsdev || !input) {
642                 dev_err(&pdev->dev, "unable to allocate memory\n");
643                 err = -ENOMEM;
644                 goto err_free_mem;
645         }
646
647         tsdev->dev = &pdev->dev;
648         tsdev->input = input;
649         tsdev->irq = irq;
650
651         snprintf(tsdev->phys, sizeof(tsdev->phys),
652                  "%s/input0", dev_name(tsdev->dev));
653
654         err = mrstouch_adc_init(tsdev);
655         if (err) {
656                 dev_err(&pdev->dev, "ADC initialization failed\n");
657                 goto err_free_mem;
658         }
659
660         input->name = "mrst_touchscreen";
661         input->phys = tsdev->phys;
662         input->dev.parent = tsdev->dev;
663
664         input->id.vendor = tsdev->vendor;
665         input->id.version = tsdev->rev;
666
667         input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
668         input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
669
670         input_set_abs_params(tsdev->input, ABS_X,
671                              MRST_X_MIN, MRST_X_MAX, MRST_X_FUZZ, 0);
672         input_set_abs_params(tsdev->input, ABS_Y,
673                              MRST_Y_MIN, MRST_Y_MAX, MRST_Y_FUZZ, 0);
674         input_set_abs_params(tsdev->input, ABS_PRESSURE,
675                              MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0);
676
677         err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq,
678                                    0, "mrstouch", tsdev);
679         if (err) {
680                 dev_err(tsdev->dev, "unable to allocate irq\n");
681                 goto err_free_mem;
682         }
683
684         err = input_register_device(tsdev->input);
685         if (err) {
686                 dev_err(tsdev->dev, "unable to register input device\n");
687                 goto err_free_irq;
688         }
689
690         platform_set_drvdata(pdev, tsdev);
691         return 0;
692
693 err_free_irq:
694         free_irq(tsdev->irq, tsdev);
695 err_free_mem:
696         input_free_device(input);
697         kfree(tsdev);
698         return err;
699 }
700
701 static int __devexit mrstouch_remove(struct platform_device *pdev)
702 {
703         struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
704
705         free_irq(tsdev->irq, tsdev);
706         input_unregister_device(tsdev->input);
707         kfree(tsdev);
708
709         platform_set_drvdata(pdev, NULL);
710
711         return 0;
712 }
713
714 static struct platform_driver mrstouch_driver = {
715         .driver = {
716                 .name   = "pmic_touch",
717                 .owner  = THIS_MODULE,
718         },
719         .probe          = mrstouch_probe,
720         .remove         = __devexit_p(mrstouch_remove),
721 };
722
723 static int __init mrstouch_init(void)
724 {
725         return platform_driver_register(&mrstouch_driver);
726 }
727 module_init(mrstouch_init);
728
729 static void __exit mrstouch_exit(void)
730 {
731         platform_driver_unregister(&mrstouch_driver);
732 }
733 module_exit(mrstouch_exit);
734
735 MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
736 MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
737 MODULE_LICENSE("GPL");