]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/input/touchscreen/omap/ts_osk.c
45b4eb9a3786d39365595000df62fce99bab4510
[linux-2.6-omap-h63xx.git] / drivers / input / touchscreen / omap / ts_osk.c
1 /*
2  * ts_osk.c - touchscreen support for OMAP OSK board
3  * 
4  * Copyright 2002 MontaVista Software Inc.
5  * Author: MontaVista Software, Inc.
6  *              stevel@mvista.com or source@mvista.com
7  *
8  * The touchscreen hardware on the OSK uses OMAP5912 uWire interface,
9  * GPIO4 (/PENIRQ) and GPIO6 (BUSY) to connect to an ADS7846 
10  * touch screen controller. GPIO6 doesn't seem to be necessary here.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  */
26
27 #include <linux/input.h>
28 #include <linux/device.h>
29 #include <asm/arch/mux.h>
30 #include <asm/arch/gpio.h>
31 #include <asm/mach-types.h>
32
33 #include "../drivers/ssi/omap-uwire.h"
34
35 #include "omap_ts.h"
36 #include "ads7846.h"
37
38 // /PENIRQ on GPIO4 on OSK
39 #define PEN_IRQ          OMAP_GPIO_IRQ(4)
40
41 // ADS7846 is on OSK uWire CS 0
42 #define ADS7846_UWIRE_CS        0
43 #define UWIRE_LEAVE_CS          1
44
45 #define X_PLATE_OHMS 419
46 #define Y_PLATE_OHMS 486
47
48 static int osk_ts_penup(void);
49 static int osk_ts_probe(struct omap_ts_t *ts);
50 static void osk_ts_read(u16 * data);
51 static void osk_ts_enable(void);
52 static void osk_ts_disable(void);
53 #ifdef MODULE
54 static void osk_ts_remove(void);
55 #endif
56
57 struct ts_device osk_ts = {
58         .probe   = osk_ts_probe,
59         .read    = osk_ts_read,
60         .enable  = osk_ts_enable,
61         .disable = osk_ts_disable,
62         .remove  = __exit_p(osk_ts_remove),
63         .penup   = osk_ts_penup,
64 };
65
66 static u16 ads7846_do(u8 cmd)
67 {
68         u16 val = 0;
69         
70         // send the command to the ADS7846, leave CS active after this
71         omap_uwire_data_transfer(ADS7846_UWIRE_CS, cmd, 8, 0, NULL, UWIRE_LEAVE_CS);
72
73         // now read returned data
74         omap_uwire_data_transfer(ADS7846_UWIRE_CS, 0, 0, 16, &val, !UWIRE_LEAVE_CS);
75         
76         return val;
77 }
78
79 static int osk_ts_penup(void)
80 {
81         return (omap_get_gpio_datain(4));
82 }
83
84 static int  __init osk_ts_probe(struct omap_ts_t *ts)
85 {
86 #ifdef  CONFIG_OMAP_OSK_MISTRAL
87         if (!machine_is_omap_osk())
88                 return -ENODEV;
89
90         /* Configure GPIO4 (pin M17 ZDY) as /PENIRQ interrupt input */
91         omap_cfg_reg(P20_1610_GPIO4);
92         omap_request_gpio(4);
93         omap_set_gpio_direction(4, 1);
94         set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
95
96         ts->irq = PEN_IRQ;
97
98         /* Configure uWire interface. ADS7846 is on CS0 */
99         omap_uwire_configure_mode(ADS7846_UWIRE_CS, UWIRE_READ_RISING_EDGE |
100                                                     UWIRE_WRITE_RISING_EDGE |
101                                                     UWIRE_CS_ACTIVE_LOW |
102                                                     UWIRE_FREQ_DIV_2);
103
104         /* FIXME verify there's really a Mistral board:
105          * see if the AD7846 chip responds.
106          */
107
108         /* NOTE:  no VREF; must ignore the temp, VBAT, and AUX sensors */
109         return 0;
110 #else
111         return -ENODEV;
112 #endif
113 }
114
115 static void osk_ts_read(u16 *data)
116 {
117         unsigned int Rt = 0;
118
119         data[0] = ads7846_do(MEASURE_12BIT_X);
120         data[1] = ads7846_do(MEASURE_12BIT_Y); 
121         data[2] = ads7846_do(MEASURE_12BIT_Z1); 
122         data[3] = ads7846_do(MEASURE_12BIT_Z2); 
123
124         // Calculate touch pressure resistance
125         if (data[2]) {
126                 Rt = (X_PLATE_OHMS * (u32)data[0] *
127                      ((u32)data[3] - (u32)data[2])) / (u32)data[2];
128
129                 Rt = (Rt + 2048) >> 12; // round up to nearest ohm
130         }
131
132         /* 
133          * Raw OSK touchscreen data values are between ~4000 and
134          * ~60000. This seems to be to large for calibration 
135          * systems (e.g. tslib). Make the values smaller.
136          */
137         data[0] = data[0] >> 4;
138         data[1] = data[1] >> 4;
139
140         data[2] = Rt;
141 }
142
143 static void osk_ts_enable(void)
144 {
145
146 }
147
148 static void osk_ts_disable(void)
149 {
150
151 }
152
153 #ifdef MODULE
154 static void __exit osk_ts_remove(void)
155 {
156         omap_free_gpio(4);
157 }
158 #endif