2 * MX1 touchscreen driver
5 * Radek Pupak (pupakr1@fel.cvut.cz)
6 * Czech Technical University, FEE, DCE
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This code is heavily based on ucb*.c copyrighted by Russell King
13 * and Nicolas Pitre covering the UCB1100, UCB1200, UCB1300 and UCB1400.
15 * Hardware specific properties are based on mx1ts.h and mx1ts.c copyrated
16 * by Blue Mug, Inc. for Motorola, Inc.
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/input.h>
24 #include <linux/interrupt.h>
25 #include <sound/driver.h>
27 #include <linux/platform_device.h>
30 /* Interrupt numbers */
31 #define ASP_COMPARE_IRQ 5
32 #define ASP_PENDATA_IRQ 33
33 #define ASP_TOUCH_IRQ 46
35 /* Analog signal processor (ASP) control registers */
36 #define ASP_BASE_ADDR 0x00215000
37 #define ASP_BASE_ADDR_LEN 0x38
39 #define ASP_ACNTLCR (0x10) /* Control register */
40 #define ASP_PSMPLRG (0x14) /* Pen A/D sampe rate control */
41 #define ASP_CMPCNTL (0x30) /* Compare control register */
42 #define ASP_ICNTLR (0x18) /* Interrupt control register */
43 #define ASP_ISTATR (0x1C) /* Interrupt status register */
44 #define ASP_PADFIFO (0x00) /* Pen sample FIFO */
45 #define ASP_CLKDIV (0x2C) /* Clock divide register */
47 /* ASP control register bits */
48 #define ASP_CLKEN (1 << 25) /* Clock enable */
49 #define ASP_SWRST (1 << 23) /* Software reset */
50 #define ASP_U_SEL (1 << 21) /* U-channel resistor select */
51 #define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */
52 #define ASP_LVM (1 << 19) /* Low voltage output */
53 #define ASP_NM (1 << 18) /* Normal voltage output */
54 #define ASP_HPM (1 << 17) /* High voltage output */
55 #define ASP_GLO (1 << 16) /* Low gain enable */
56 #define ASP_AZE (1 << 15) /* Auto-zero enable */
57 #define ASP_AUTO (1 << 14) /* Auto sampling */
58 #define ASP_SW8 (1 << 11) /* Switch control 8 */
59 #define ASP_SW7 (1 << 10)
60 #define ASP_SW6 (1 << 9)
61 #define ASP_SW5 (1 << 8)
62 #define ASP_SW4 (1 << 7)
63 #define ASP_SW3 (1 << 6)
64 #define ASP_SW2 (1 << 5)
65 #define ASP_SW1 (1 << 4) /* Switch control 1 */
66 #define ASP_VDAE (1 << 3) /* Voice D/A enable */
67 #define ASP_VADE (1 << 2) /* Voice A/D enable */
68 #define ASP_PADE (1 << 1) /* Pen A/D enable */
69 #define ASP_BGE (1 << 0) /* Bandgap enable */
71 #define ASP_MODE_MASK 0x00003000
72 #define ASP_MODE_NONE 0x00000000
73 #define ASP_MODE_ONLY_X 0x00001000
74 #define ASP_MODE_ONLY_Y 0x00002000
75 #define ASP_MODE_ONLY_U 0x00003000
77 /* ASP Pen A/D sample rate control register */
78 #define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */
79 #define ASP_DMCNT_SCALE (12)
80 #define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */
81 #define ASP_BIT_SELECT_SCALE (10)
82 #define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */
83 #define ASP_IDLECNT_SCALE (4)
84 #define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */
85 #define ASP_DSCNT_SCALE (0)
87 /* ASP compare control register */
88 #define ASP_INT (1 << 19) /* Interrupt status */
89 #define ASP_CC (1 << 18) /* Trigger on greater than */
90 #define ASP_INSEL_MASK (0x00030000)
91 #define ASP_INSEL_DISABLE (0x00000000)
92 #define ASP_INSEL_X (0x00010000)
93 #define ASP_INSEL_Y (0x00020000)
94 #define ASP_INSEL_U (0x00030000)
95 #define ASP_COMPARE_VAL_MASK (0x0000FFFF)
96 #define ASP_COMPARE_VAL_SCALE (0)
98 /* ASP interrupt control register bits */
99 #define ASP_PUIE (1 << 10) /* Pen up XXX undocumented */
100 #define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */
101 #define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */
102 #define ASP_POL (1 << 6) /* Pen interrupt polarity */
103 #define ASP_EDGE (1 << 5) /* Edge trigger enable */
104 #define ASP_PIRQE (1 << 4) /* Pen interrupt enable */
105 #define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */
106 #define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */
107 #define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */
108 #define ASP_PDRE (1 << 0) /* Pen data ready interrupt */
110 /* ASP interrupt/error status register bits */
111 #define ASP_PUIS (1 << 10) /* Pen-up Status,event-> clear by 1 */
112 #define ASP_BGR (1 << 9) /* Bandgap ready */
113 #define ASP_VOV (1 << 8) /* Voice sample data overflow */
114 #define ASP_POV (1 << 7) /* Pen sample data overflow */
115 #define ASP_PEN (1 << 6) /* Pen interrupt */
116 #define ASP_VDAFF (1 << 5) /* VDAC FIFO full */
117 #define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */
118 #define ASP_VADFF (1 << 3) /* VADC FIFO full */
119 #define ASP_VADDR (1 << 2) /* VADC data ready */
120 #define ASP_PFF (1 << 1) /* Pen sample FIFO full */
121 #define ASP_PDR (1 << 0) /* Pen data ready */
123 /* ASP Clock divide register */
124 #define ASP_PADC_CLK_MASK (0x0000001F)
125 #define ASP_PADC_CLK_SCALE (0)
126 #define ASP_VADC_CLK_MASK (0x000003E0)
127 #define ASP_VADC_CLK_SCALE (5)
128 #define ASP_VDAC_CLK_MASK (0x00003C00)
129 #define ASP_VDAC_CLK_SCALE (10)
131 #define DEV_IRQ_ID "mx1-ts"
134 struct input_dev *ts_idev;
135 /*struct resource pamet;*/
136 unsigned int irq_touch;
137 unsigned int irq_pen_data;
139 wait_queue_head_t ts_wait;
140 struct task_struct *ts_task;
142 void __iomem* mx1ts_mem; /* remaped memmory */
143 unsigned int baseaddr;
144 unsigned int baseaddr_len;
153 /*unsigned int stav; */
160 static inline void mx1ts_reg_set_mask(struct mx1ts *mts , unsigned int reg, u32 mask)
163 val = __raw_readl(mts->mx1ts_mem+reg); /* TODO zvazit pouziti ioread32 */
165 __raw_writel(val, mts->mx1ts_mem+reg );
168 static inline void mx1ts_reg_clear_mask(struct mx1ts *mts , unsigned int reg, u32 mask)
171 val = __raw_readl(mts->mx1ts_mem+reg);
173 __raw_writel(val, mts->mx1ts_mem+reg );
176 static inline void mx1ts_reg_write(struct mx1ts *mts, unsigned int reg, unsigned int val)
178 __raw_writel(val, mts->mx1ts_mem+reg);
179 /*printk(KERN_DEBUG "mx1_touchscreen: writing into : %p value %x\n",mts->mx1ts_mem+reg, val);*/
183 static inline unsigned int mx1ts_reg_read(struct mx1ts *mts, unsigned int reg)
186 out = __raw_readl( mts->mx1ts_mem + reg );
187 /*printk(KERN_DEBUG "mx1_touchscreen: reading from %p : %d \n",mts->mx1ts_mem + reg, out);*/
192 static inline void mx1ts_flush_fifo(struct mx1ts *mts)
195 for (i = 0; i < 12; i++)
196 if (mx1ts_reg_read(mts, ASP_ISTATR) & (ASP_PFF | ASP_PDR))
197 mx1ts_reg_read(mts, ASP_PADFIFO);
200 static void mx1ts_enable_auto_sample(struct mx1ts *mts)
203 mx1ts_flush_fifo(mts);
205 value = mx1ts_reg_read(mts, ASP_ACNTLCR);
207 /* Set the mode to X then Y */
208 value &= ~ASP_MODE_MASK;
209 value |= ASP_MODE_ONLY_Y;
211 /* Enable auto zero. */
214 /* Enable auto sample. */
217 /* Enable pen A/D. */
219 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
221 /* Enable pen data ready and full interrupt. */
222 value = mx1ts_reg_read(mts, ASP_ICNTLR);
223 value |= ASP_PFFE | ASP_PDRE;
224 mx1ts_reg_write(mts, ASP_ICNTLR, value);
228 static void mx1ts_disable_auto_sample(struct mx1ts *mts)
232 value = mx1ts_reg_read(mts, ASP_ACNTLCR);
234 /* Set the mode to none */
235 value &= ~ASP_MODE_MASK;
237 /* Disable auto zero. */
240 /* Disable auto sample. */
243 /* Disable pen A/D. */
245 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
247 /* Disable pen data ready and full interrupt. */
248 value = mx1ts_reg_read(mts, ASP_ICNTLR);
249 value &= ~(ASP_PFFE | ASP_PDRE);
250 mx1ts_reg_write(mts, ASP_ICNTLR, value);
253 static void mx1ts_enable_pen_touch_interrupt(struct mx1ts *mts)
257 /* Enable pen touch interrupt. */
258 value = mx1ts_reg_read(mts, ASP_ICNTLR);
259 value |= ASP_EDGE | /*ASP_POL |*/ ASP_PIRQE;
260 mx1ts_reg_write(mts, ASP_ICNTLR, value);
262 printk(KERN_DEBUG "mx1_touchscreen: pen_touch: activating pen_down interrupt \n");
265 static void mx1ts_disable_pen_touch_interrupt(struct mx1ts *mts)
269 /* Enable pen touch interrupt. */
270 value = mx1ts_reg_read(mts, ASP_ICNTLR);
272 mx1ts_reg_write(mts, ASP_ICNTLR, value);
273 printk(KERN_DEBUG "mx1_touchscreen: pen_touch: deaktivating pen_down interrupt \n");
276 static void mx1ts_enable_pen_up_interrupt(struct mx1ts *mts)
280 value = mx1ts_reg_read(mts, ASP_ICNTLR);
282 mx1ts_reg_write(mts, ASP_ICNTLR, value);
283 printk(KERN_DEBUG "mx1_touchscreen: pen_up: activating pen_up interrupt \n");
286 static void mx1ts_disable_pen_up_interrupt(struct mx1ts *mts)
290 /* Enable pen up interrupt. */
291 value = mx1ts_reg_read(mts, ASP_ICNTLR);
293 mx1ts_reg_write(mts, ASP_ICNTLR, value);
294 printk(KERN_DEBUG "mx1_touchscreen: pen_up: deaktivating pen_up interrupt \n");
299 static void mx1ts_start_auto_calibration(struct mx1ts *mts)
302 printk(KERN_DEBUG "mx1_touchscreen: start_auto_calibration \n");
305 mts->auto_calibration = 1;
307 value = mx1ts_reg_read(mts, ASP_ACNTLCR);
309 /* Set the mode to X then Y */
310 value &= ~ASP_MODE_MASK;
311 value |= ASP_MODE_ONLY_X;
313 /* Enable auto zero. */
316 /* Enable auto calibrate. XXX: Undocumented bitfield. */
319 /* Enable auto sample. */
322 /* Enable pen A/D. */
324 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
326 /* Enable pen data ready and full interrupt. */
327 value = mx1ts_reg_read(mts, ASP_ICNTLR);
328 value |= ASP_PFFE | ASP_PDRE | ASP_PUIE;
329 mx1ts_reg_write(mts, ASP_ICNTLR, value);
332 static void mx1ts_reset_asp(struct mx1ts *mts)
336 mx1ts_flush_fifo(mts);
338 /* Soft reset the ASP module */
339 mx1ts_reg_write(mts, ASP_ACNTLCR, ASP_SWRST);
340 /* Read back the reset value of the control register */
341 value = mx1ts_reg_read(mts, ASP_ACNTLCR);
343 /* Enable the clock and wait for a short while */
345 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
348 /* Set the value of the conrtol register. */
349 value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
350 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
352 /* 0x01 Set the clock divide ratio to 2. */
353 mx1ts_reg_write(mts, ASP_CLKDIV, 0x1f);
355 /* Set the sample rate control register. These values should yield
356 * about 150 samples per second, which seems to give good smooth
358 value = (0x7 << ASP_DMCNT_SCALE) | /* 0x2 - Decimation ratio is 3 */
359 (0x3F << ASP_IDLECNT_SCALE) | /* 0x1 - Idle count is 1 clock */
360 (0xF << ASP_DSCNT_SCALE); /* 0x2 - Data setup is 2 clocks */
361 mx1ts_reg_write(mts, ASP_PSMPLRG, value);
363 /* Disable the compare function. */
364 mx1ts_reg_write(mts, ASP_CMPCNTL, 0);
367 static void mx1ts_evt_add_touch(struct input_dev *idev, u8 p , u16 x, u16 y)
369 struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
373 input_report_key(idev, BTN_TOUCH, 1);
374 input_report_abs(idev, ABS_X, x);
375 input_report_abs(idev, ABS_Y, y);
376 /*input_report_abs(idev, ABS_PRESSURE, p);*/
377 input_report_abs(idev, ABS_PRESSURE, 1);
381 static void mx1ts_evt_add_up(struct input_dev *idev)
383 struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
385 input_report_abs(idev, ABS_X, mts->x_akt);
386 input_report_abs(idev, ABS_Y, mts->y_akt);
387 input_report_abs(idev, ABS_PRESSURE, 0);
388 /*input_report_key(idev, BTN_TOUCH, 0);*/
393 * Handle the pen data ready interrupt, generated when pen data is
397 static irqreturn_t mx1ts_pendata_irq(int irq, void *dev_id)
400 struct mx1ts *mts = (struct mx1ts *)dev_id;
403 static unsigned int auto_zero, pen_x, pen_y, pen_u;
408 /*printk(KERN_DEBUG "mx1_touchscreen: mx1_pendata_irq interrupt recived from struct %p\n", mts);*/
410 if (mx1ts_reg_read(mts, ASP_ISTATR) & ASP_PUIS) { /*pen up interupt pending*/
411 mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PUIS); /*clearing pen up interupt*/
413 mx1ts_disable_auto_sample(mts);
414 mx1ts_disable_pen_up_interrupt(mts);
415 mx1ts_enable_pen_touch_interrupt(mts);
417 if(mts->is_open) /*report last known touch*/
418 mx1ts_evt_add_up(mts->ts_idev);
419 printk(KERN_DEBUG "Pen up interrupt.\n");
420 mx1ts_flush_fifo(mts);
425 if (mts->auto_calibration) {
426 /* unsigned int value;*/
428 mts->cal_auto_zero = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
429 mts->cal_range_x = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
430 mts->cal_range_y = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
432 if ((mts->cal_auto_zero >= mts->cal_range_x) ||
433 (mts->cal_auto_zero >= mts->cal_range_y)) {
435 printk(KERN_INFO "Invalid calibration data. Recalibrating. \n");
436 mx1ts_flush_fifo(mts); /*if there are some older data*/
437 mx1ts_start_auto_calibration(mts);
438 return IRQ_HANDLED; /*return IRQ_NONE;*/
441 printk(KERN_DEBUG "mx1 touchscreen: calibration cal_auto_zero %i.\n",mts->cal_auto_zero);
442 printk(KERN_DEBUG "mx1 touchscreen: calibration cal_range_x %i.\n",mts->cal_range_x);
443 printk(KERN_DEBUG "mx1 touchscreen: calibration cal_range_y %i.\n",mts->cal_range_y);
445 mts->cal_range_x -= mts->cal_auto_zero;
446 mts->cal_range_y -= mts->cal_auto_zero;
450 value = mx1ts_reg_read(mts, ASP_ACNTLCR); podle me duplicita
451 value &= ~0x04000000;
452 mx1ts_reg_write(mts, ASP_ACNTLCR, value);
454 mts->auto_calibration = 0;
456 mx1ts_enable_auto_sample(mts);
458 // There could be more than one sample in the FIFO, but we're
459 // only going to read one per call. The interrupt will be
460 // generated as long as there is data in the FIFO.
462 if ((mx1ts_reg_read(mts, ASP_ISTATR) & ASP_PDR) != ASP_PDR) {
466 auto_zero = mx1ts_reg_read(mts, ASP_PADFIFO);
467 if (auto_zero > (mts->cal_auto_zero + 0x200)) {
468 return IRQ_HANDLED; /* TODO asi se nic nedeje */
471 pen_x = mx1ts_reg_read(mts, ASP_PADFIFO);
472 pen_y = mx1ts_reg_read(mts, ASP_PADFIFO);
473 pen_u = mx1ts_reg_read(mts, ASP_PADFIFO);
475 pen_x = mts->x_res - (u32)(((pen_x - auto_zero) << 16) /
477 pen_y = mts->y_res - (u32)(((pen_y - auto_zero) << 16) /
481 mx1ts_evt_add_touch(mts->ts_idev, 200 , pen_x, pen_y);
487 * Handle the touch interrupt, generated when the pen is pressed/
491 static irqreturn_t mx1ts_touch_irq(int irq, void *dev_id)
493 struct mx1ts *mts = (struct mx1ts *) dev_id;
495 printk(KERN_DEBUG "mx1 touchscreen: Touch down interrupt \n");
497 /* Clear the interrupt. */
498 mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PEN);
500 mx1ts_disable_pen_touch_interrupt(mts);
501 mx1ts_flush_fifo(mts);
502 mx1ts_start_auto_calibration(mts);
503 mx1ts_enable_pen_up_interrupt(mts);
508 static inline int mx1ts_enable_irqs(struct mx1ts *mts) //zaregistruje preruseni
512 result = request_irq(mts->irq_pen_data,
518 printk(KERN_ERR "mx1 touchscreen: Couldn't request pen data IRQ.\n");
522 result = request_irq(mts->irq_touch,
528 printk(KERN_ERR "mx1 touchscreen: Couldn't request pen touch IRQ.\n");
529 free_irq(mts->irq_pen_data, mts);
537 static int mx1ts_on(struct mx1ts *mts)
541 if(!request_mem_region(mts->baseaddr, mts->baseaddr_len , "mx1ts")) {
542 printk(KERN_ERR "mx1 touchscreen: request_mem_region \tFAILED\n");
546 printk(KERN_DEBUG "mx1 touchscreen: request_mem_region \tOK\n");
548 mts->mx1ts_mem = ioremap ( mts->baseaddr, mts->baseaddr_len);
550 if(!mts->mx1ts_mem) {
551 release_mem_region(mts->baseaddr, mts->baseaddr_len);
552 printk(KERN_ERR "mx1 touchscreen: ioremap \tFAILED\n");
556 printk(KERN_DEBUG "mx1 touchscreen: memory remaped on %p \n", mts->mx1ts_mem);
560 /*printk(KERN_DEBUG "mx1 touchscreen: enabling irqs\n");*/
561 if ((ret = mx1ts_enable_irqs(mts)))
563 printk(KERN_DEBUG "mx1 touchscreen: irqs enabled \tOK\n");
566 mx1ts_reset_asp(mts);
567 printk(KERN_DEBUG "mx1 touchscreen: reset\tOK\n");
572 static void mx1ts_close(struct input_dev *idev)
574 struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
576 mx1ts_flush_fifo(mts);
577 mx1ts_reset_asp(mts);
578 printk(KERN_DEBUG "mx1 touchscreen: reset\tOK\n");
579 mx1ts_disable_pen_touch_interrupt(mts);
580 mx1ts_disable_pen_up_interrupt(mts);
584 static int mx1ts_open(struct input_dev *idev)
586 struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
588 mx1ts_flush_fifo(mts); /*if there are some older data*/
589 mx1ts_enable_pen_touch_interrupt(mts);
590 printk(KERN_DEBUG "mx1 touchscreen: touch_down interupt enabled\n");
594 static int mx1ts_probe(struct platform_device *dev)
597 struct input_dev *idev;
600 /* TODO jak poznat ze zarizeni je pritomne ? */
602 mts = kzalloc(sizeof(struct mx1ts), GFP_KERNEL);
603 idev = input_allocate_device();
606 printk(KERN_ERR "mx1 touchscreen: failed allocate memory for struct mx1ts or idev\n");
610 mts->baseaddr = dev->resource[0].start;
611 mts->baseaddr_len = dev->resource[0].end - dev->resource[0].start;
612 printk(KERN_ERR "mx1 touchscreen: memorry base addr %d \n", mts->baseaddr);
613 printk(KERN_ERR "mx1 touchscreen: memorry base addr_len %d \n", mts->baseaddr_len);
614 mts->irq_pen_data = dev->resource[1].start;
615 mts->irq_touch = dev->resource[2].start;
617 error = mx1ts_on(mts);
618 if(error<0) { /* remaping registers, reseting device */
619 printk(KERN_ERR "mx1 touchscreen: failed mx1ts_on - remaping registers, reseting device\n");
625 init_waitqueue_head(&mts->ts_wait);
627 //input_set_drvdata(idev, mts); /*moznost ulozit ukazatel na trukturu do input_driver*/
628 platform_set_drvdata(dev, mts);
630 idev->dev.parent = &dev->dev;
631 idev->name = "MX1 touchscreen interface";
632 idev->phys = "mx1ts/input0";
633 idev->id.vendor = (unsigned int) 345; /*mx1ts_reg_read(mx1_ts, AC97_VENDOR_ID1);*/
634 idev->id.product = (unsigned int) 354;
635 idev->id.version = 0x0100;
636 idev->id.bustype = BUS_HOST;
637 idev->open = mx1ts_open;
638 idev->close = mx1ts_close;
639 idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
640 idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
642 printk(KERN_DEBUG "mx1ts: setting idev struct \tOK\n");
644 mts->x_res = 60000; /*TODO neni mozne zmerit ? */
646 printk(KERN_DEBUG "mx1ts: x/y = %d/%d\n", mts->x_res, mts->y_res);
648 input_set_abs_params(idev, ABS_X, 0, mts->x_res, 0, 0);
649 input_set_abs_params(idev, ABS_Y, 0, mts->y_res, 0, 0);
650 input_set_abs_params(idev, ABS_PRESSURE, 0, 1, 0, 0);
652 error = input_register_device(idev);
654 printk(KERN_ERR "mx1 touchscreen: error while register input device\n");
658 printk(KERN_DEBUG "mx1ts: input device registered \tOK\n");
663 printk(KERN_ERR "mx1 touchscreen: error in device probe \n");
664 input_free_device(idev);
672 static int mx1ts_remove(struct platform_device *dev)
674 struct mx1ts *mts = platform_get_drvdata(dev);
676 //BUG_ON(mts == NULL);
678 free_irq(mts->irq_pen_data, mts);
679 free_irq(mts->irq_touch, mts);
681 /*input_free_device(mts->ts_idev);
682 printk(KERN_DEBUG "Free device \tOK\n");*/
684 input_unregister_device(mts->ts_idev);
685 printk(KERN_INFO "mx1 touchscreen: Unregister device \tOK\n");
686 iounmap(mts->mx1ts_mem);
687 release_mem_region(mts->baseaddr, mts->baseaddr_len);
691 printk(KERN_INFO "mx1 touchscreen: Removing driver \tOK\n");
697 static int mx1ts_resume(struct platform_device *dev)
702 static struct platform_driver mx1ts_driver = {
703 .probe = mx1ts_probe,
704 .remove = mx1ts_remove,
705 .resume = mx1ts_resume,
708 .owner = THIS_MODULE,
712 static struct resource mx1ts_resources[] = {
714 .start = ASP_BASE_ADDR + 0,
715 .end = ASP_BASE_ADDR + ASP_BASE_ADDR_LEN,
716 .flags = IORESOURCE_MEM,
719 .start = ASP_PENDATA_IRQ,
720 .end = ASP_PENDATA_IRQ,
721 .flags = IORESOURCE_IRQ,
724 .start = ASP_TOUCH_IRQ,
725 .end = ASP_TOUCH_IRQ,
726 .flags = IORESOURCE_IRQ,
730 void mx1ts_device_release(struct device *dev) {
731 /*struct platform_device *pdev = to_platform_device(dev);
732 release_resource(&dev->res);
737 static struct platform_device mx1ts_device = {
740 .num_resources = ARRAY_SIZE(mx1ts_resources),
741 .resource = mx1ts_resources,
743 .release = mx1ts_device_release,
750 static int __init mx1ts_init(void)
754 error = platform_device_register(&mx1ts_device);
756 printk(KERN_ERR "mx1 touchscreen: device registration failed\n");
761 error = platform_driver_register(&mx1ts_driver);
763 printk(KERN_ERR "mx1_touchscreen: failed to register touchscreen driver, error: %d\n", error);
764 platform_device_unregister(&mx1ts_device);
773 static void __exit mx1ts_exit(void)
775 platform_driver_unregister(&mx1ts_driver);
776 platform_device_unregister(&mx1ts_device);
781 //module_param(adcsync, bool, 0444); /* priklad parametru modulu*/
782 //MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
784 module_init(mx1ts_init);
785 module_exit(mx1ts_exit);
788 MODULE_DESCRIPTION("MX1 touchscreen driver");
789 MODULE_AUTHOR("Radek Pupák (pupakr1@fel.cvut.cz)");
790 MODULE_LICENSE("GPL");