]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/input/touchscreen/omap/ts_inn1510.c
b85f0032771a7d7e900f6f692efc57a9b48e291d
[linux-2.6-omap-h63xx.git] / drivers / input / touchscreen / omap / ts_inn1510.c
1 /*
2  * ts_inn1510.c - touchscreen support for OMAP1510 Innovator 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 Innovator consists of an FPGA
9  * register which is bit-banged to generate SPI-like transactions
10  * to an ADS7846 touch screen controller.
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/io.h>
30 #include <asm/mach-types.h>
31 #include <asm/arch/fpga.h>
32
33 #include "omap_ts.h"
34 #include "ads7846.h"
35
36 // The Touch Screen Register on Innovator FPGA
37 #define FPGA_TS_BCLK     (1<<0)
38 #define FPGA_TS_BDIN     (1<<1)
39 #define FPGA_TS_BCS      (1<<2)
40 #define FPGA_TS_BBUSY    (1<<3)
41 #define FPGA_TS_BOUT     (1<<4)
42 #define FPGA_TS_BPENUP   (1<<5)
43
44 #define X_PLATE_OHMS 419
45 #define Y_PLATE_OHMS 486
46
47 static int inn1510_ts_penup(void);
48 static int inn1510_ts_probe(struct omap_ts_t *ts);
49 static void inn1510_ts_read(u16 * data);
50 static void inn1510_ts_enable(void);
51 static void inn1510_ts_disable(void);
52 #ifdef MODULE
53 static void inn1510_ts_remove(void);
54 #endif
55
56 struct ts_device innovator1510_ts = {
57         .probe   = inn1510_ts_probe,
58         .read    = inn1510_ts_read,
59         .enable  = inn1510_ts_enable,
60         .disable = inn1510_ts_disable,
61         .remove  = __exit_p(inn1510_ts_remove),
62         .penup   = inn1510_ts_penup,
63 };
64
65 static inline u8 fpga_ts_read(void)
66 {
67         return fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
68 }
69
70 static inline void fpga_ts_write(u8 val)
71 {
72         fpga_write(val, OMAP1510_FPGA_TOUCHSCREEN);
73 }
74
75 static inline void fpga_ts_set_bits(u8 mask)
76 {
77         fpga_ts_write(fpga_ts_read() | mask);
78 }
79
80 static inline void fpga_ts_clear_bits(u8 mask)
81 {
82         fpga_ts_write(fpga_ts_read() & ~mask);
83 }
84
85 static inline void CS_H(void)
86 {
87         // EPLD inverts active low signals.
88         fpga_ts_clear_bits(FPGA_TS_BCS);
89 }
90
91 static inline void CS_L(void)
92 {
93         fpga_ts_set_bits(FPGA_TS_BCS);
94 }
95
96 static inline void SCLK_L(void)
97 {
98         fpga_ts_clear_bits(FPGA_TS_BCLK);
99 }
100
101 static inline void SCLK_H(void)
102 {
103         fpga_ts_set_bits(FPGA_TS_BCLK);
104 }
105
106 static inline void SDI_L(void)
107 {
108         fpga_ts_clear_bits(FPGA_TS_BDIN);
109 }
110
111 static inline void SDI_H(void)
112 {
113         fpga_ts_set_bits(FPGA_TS_BDIN);
114 }
115
116 static inline int BUSY(void)
117 {
118         return (((fpga_ts_read() & FPGA_TS_BBUSY) == 0) ? 1 : 0) ;
119 }
120
121 static inline u8 DOUT(void)
122 {        
123         return ((fpga_ts_read() & FPGA_TS_BOUT) ? 1 : 0) ;
124 }
125
126 static u16 ads7846_do(u8 cmd)
127 {  
128         int i;
129         u16 val=0;
130
131         SCLK_L() ;
132         SDI_L();
133         CS_L() ;        // enable the chip select
134
135         // send the command to the ADS7846
136         for (i=0; i<8; i++ ) {
137                 if (cmd & 0x80)
138                         SDI_H();
139                 else
140                         SDI_L();   // prepare the data on line sdi OR din
141
142                 SCLK_H() ;      // clk in the data
143                 cmd <<= 1 ;
144                 SCLK_L() ;
145         }
146
147         SDI_L();
148         while (BUSY())
149                 ;
150
151         // now read returned data
152         for (i=0 ; i<16 ; i++ ) {
153                 SCLK_L() ;
154                 
155                 if (i < 12) {
156                         val <<= 1 ;
157                         val |= DOUT();
158                 }
159                 SCLK_H() ;
160         }
161
162         SCLK_L() ;
163         CS_H() ;   // disable the chip select
164
165         return val;
166 }
167
168 static int inn1510_ts_penup(void)
169 {
170         return ((fpga_ts_read() & FPGA_TS_BPENUP) ? 0 : 1) ;
171 }
172
173 static int __init inn1510_ts_probe(struct omap_ts_t *ts)
174 {
175         if (!cpu_is_omap15xx() || !machine_is_omap_innovator())
176                 return -ENODEV;
177
178         ts->irq = OMAP1510_INT_FPGA_TS;
179         
180         return 0;
181 }
182
183 static void inn1510_ts_read(u16 *data)
184 {
185         unsigned int Rt = 0;
186
187         data[0] = ads7846_do(MEASURE_12BIT_X);
188         data[1] = ads7846_do(MEASURE_12BIT_Y); 
189         data[2] = ads7846_do(MEASURE_12BIT_Z1); 
190         data[3] = ads7846_do(MEASURE_12BIT_Z2); 
191
192         // Calculate touch pressure resistance
193         if (data[2]) {
194                 Rt = (X_PLATE_OHMS * (u32)data[0] *
195                      ((u32)data[3] - (u32)data[2])) / (u32)data[2];
196
197                 Rt = (Rt + 2048) >> 12; // round up to nearest ohm
198         }
199
200         data[2] = Rt;
201 }
202
203 static void inn1510_ts_enable(void)
204 {
205
206 }
207
208 static void inn1510_ts_disable(void)
209 {
210
211 }
212
213 #ifdef MODULE
214 static void __exit inn1510_ts_remove(void)
215 {
216         /* Nothing to do here */
217 }
218 #endif