]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/arm_drivers/input/src/tsc-omap3.c
ae60276585302eeae508524779223e69e6bbdd29
[l4.git] / l4 / pkg / arm_drivers / input / src / tsc-omap3.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include <pthread.h>
6 #include <pthread-l4.h>
7
8 #include <l4/input/drv_reg.h>
9 #include <l4/re/c/dataspace.h>
10 #include <l4/re/c/mem_alloc.h>
11 #include <l4/re/c/rm.h>
12 #include <l4/re/c/namespace.h>
13 #include <l4/re/c/util/cap_alloc.h>
14 #include <l4/re/event_enums.h>
15 #include <l4/io/io.h>
16 #include <l4/sys/icu.h>
17 #include <l4/sys/irq.h>
18 #include <l4/sys/thread.h>
19 #include <l4/sys/debugger.h>
20 #include <l4/util/util.h>
21 #include <l4/vbus/vbus.h>
22 #include <l4/vbus/vbus_gpio.h>
23 #include <l4/vbus/vbus_mcspi.h>
24
25 #include "tsc-omap3.h"
26
27 typedef struct {
28     int x;
29     int y;
30 } Tsc_coord;
31
32 typedef struct {
33     Tsc_coord ul;       // upper left coordinate
34     Tsc_coord lr;       // lower right coordinate
35 } Tsc_disp;
36
37 static int get_width(Tsc_disp *d)
38 { return d->lr.x - d->ul.x; }
39
40 static int get_height(Tsc_disp *d)
41 { return d->lr.y - d->ul.y; }
42
43 static int is_valid(Tsc_disp *d, int x, int y)
44 {
45   if ((x >= d->ul.x) && (x <= d->lr.x) &&
46       (y >= d->ul.y) && (y <= d->lr.y))
47     return 1;
48   else
49     return 0;
50 }
51
52 static char *omap_dev_name = "OMAP_TSC";
53
54 static Input_handler tsc_handler;
55 static void *tsc_priv;
56 static pthread_t _pthread;
57
58 static l4_cap_idx_t vbus = L4_INVALID_CAP;
59 static l4vbus_device_handle_t tsc_handle;
60 static l4vbus_device_handle_t gpio_handle;
61 static l4vbus_device_handle_t mcspi_handle;
62 static unsigned irq = 175;
63 static unsigned channel = 0; // This is fixed
64
65 // FIXME: the physical display depends on the touchscreen device
66 static Tsc_disp disp_phys = {{ 3856, 3856}, { 176, 176 }};
67 // FIXME: the virtual display depends on the LCD device
68 static Tsc_disp disp_virt = {{ 0, 0 }, { 480, 640 }};
69
70 static int tsc_init(void)
71 {
72   vbus = l4re_get_env_cap("vbus");
73
74   if (l4_is_invalid_cap(vbus))
75     {
76       printf("Failed to query vbus\n");
77       return -1;
78     }
79
80   if (l4vbus_get_device_by_hid(vbus, 0, &tsc_handle, omap_dev_name, 0, 0))
81     {
82       printf("[TSC] Cannot find TSC device\n");
83       return -L4_ENODEV;
84     }
85
86   if (l4vbus_get_device_by_hid(vbus, 0, &gpio_handle, "gpio", 0, 0))
87     {
88       printf("[TSC] Cannot find GPIO bus\n");
89       return -L4_ENODEV;
90     }
91
92   if (l4vbus_get_device_by_hid(vbus, 0, &mcspi_handle, "mcspi", 0, 0))
93     {
94       printf("[TSC] Cannot find McSPI bus\n");
95       return -L4_ENODEV;
96     }
97
98   return 0;
99 }
100
101 #if 0
102 static void tsc_get_pen_position(int *x, int *y)
103 {
104   l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
105
106   l4vbus_bus_read(2, 0x8000, &data1);
107   l4vbus_bus_read(2, 0xd300, &data2);
108   l4vbus_bus_read(2, 0x9300, &data3);
109   l4vbus_bus_read(2, 0x8000, &data4);
110   
111   // convert physical display coordinates to virtual display coordinates
112   *x = ((*x - disp_phys.ul.x) * get_width(&disp_virt))/get_width(&disp_phys) + disp_virt.ul.x;
113   *y = ((*y - disp_phys.ul.y) * get_height(&disp_virt))/get_height(&disp_phys) + disp_virt.ul.y;
114 }
115 #endif
116
117 static void tsc_get_pen_position(int *x, int *y)
118 {
119   l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
120
121   l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
122   l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data1);
123
124   l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0xd300);
125   l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data2);
126
127   l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x9300);
128   l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data3);
129
130   l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
131   l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data4);
132
133   *x = ((data2 & 0x7f) << 5) | ((data3 & 0xf800) >> 11);
134   *y = ((data3 & 0x7f) << 5) | ((data4 & 0xf800) >> 11);
135
136   // XXX convert physical display coordinates to virtual display coordinates
137   *x = ((*x - disp_phys.ul.x) * get_width(&disp_virt))/get_width(&disp_phys) + disp_virt.ul.x;
138   *y = ((*y - disp_phys.ul.y) * get_height(&disp_virt))/get_height(&disp_phys) + disp_virt.ul.y;
139   
140   //printf ("[TSC] Info: (x,y)=(%d,%d)\n", *x, *y);
141 }
142
143 l4_cap_idx_t get_icu(void);
144
145 static void create_motion_event(void)
146 {
147   int x = 0, y = 0;
148   tsc_get_pen_position(&x, &y);
149   if (is_valid(&disp_virt, x, y))
150     {
151       Input_event ev_x = { L4RE_EV_ABS, L4RE_ABS_X, x };
152       tsc_handler(ev_x, tsc_priv);
153       Input_event ev_y = { L4RE_EV_ABS, L4RE_ABS_Y, y };
154       tsc_handler(ev_y, tsc_priv);
155     }
156 }
157
158 static int tsc_irq_func(void)
159 {
160   l4_cap_idx_t irq_cap = l4re_util_cap_alloc();
161   l4_cap_idx_t thread_cap = pthread_getl4cap(_pthread);
162   l4_msgtag_t tag;
163
164   l4_debugger_set_object_name(thread_cap, "tsc-omap3.irq");
165   
166 #if 0
167   if (l4io_request_irq2(irq, irq_cap, L4_IRQ_F_NEG_EDGE) < 0)
168     return -2;
169 #endif
170   // was L4_IRQ_F_LEVEL_HIGH
171   tag = l4_irq_attach(irq_cap, 0, thread_cap);
172   if (l4_ipc_error(tag, l4_utcb()))
173     return -3;
174
175
176   while (1)
177     {
178       tag = l4_irq_receive(irq_cap, L4_IPC_NEVER);
179       if (l4_ipc_error(tag, l4_utcb()))
180         {
181           printf("[TSC] Error: Receive irq failed\n");
182           continue;
183         }
184    
185       if (!tsc_handler)
186         continue;
187       
188       create_motion_event();
189       // generate touch start event;
190       Input_event ev = { L4RE_EV_KEY, L4RE_BTN_LEFT, 1 };
191       tsc_handler(ev, tsc_priv);
192       
193       int pen_up = 0;
194       if (l4vbus_gpio_read(vbus, gpio_handle, irq, &pen_up))
195         return -6;
196       while (!pen_up)
197         {
198           create_motion_event();
199           l4_usleep(2);
200           
201           if (l4vbus_gpio_read(vbus, gpio_handle, irq, &pen_up))
202             return -6;
203         }
204       
205       // generate touch end event;
206       Input_event ev2 = { L4RE_EV_KEY, L4RE_BTN_LEFT, 0 };
207       tsc_handler(ev2, tsc_priv);
208   
209 #if 0
210       l4_umword_t label = 0;
211       l4_icu_unmask(get_icu(), irq, &label, L4_IPC_NEVER);
212 #endif
213     }
214 }
215
216 static void* __irq_func(void *data)
217 {
218   (void)data;
219   int ret = tsc_irq_func();
220   printf("[TSC] Warning: irq handler returned with:%d\n", ret);
221   l4_sleep_forever();
222 }
223
224 static const char *tsc_get_info(void)
225 { return "ARM OMAP3EVM TSC"; }
226
227 static int tsc_probe(const char *name)
228 {
229   if (strcmp(omap_dev_name, name)) {
230     printf("[TSC] I'm not the right driver for [%s]\n", name);
231     return 0;
232   }
233   return !l4io_lookup_device(omap_dev_name, NULL, 0, 0);
234 }
235
236 static void tsc_attach(Input_handler handler, void *priv)
237
238   tsc_handler = handler;
239   tsc_priv = priv;
240   pthread_attr_t thread_attr;
241
242   int err;
243   if ((err = pthread_attr_init(&thread_attr)) != 0)
244     printf("[TSC] Error: Initializing pthread attr: %d", err);
245
246   struct sched_param sp;
247   sp.sched_priority = 0x20;
248   pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
249   pthread_attr_setschedparam(&thread_attr, &sp);
250   pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
251   
252   err = pthread_create(&_pthread, &thread_attr, __irq_func, 0);
253   if (err != 0)
254     printf("[TSC] Error: Creating thread");
255 }
256
257 static void tsc_enable(void)
258 {
259   if (tsc_init())
260     {
261       printf("[TSC] Init failed!\n");
262       return;
263     }
264 }
265
266 static void tsc_disable(void)
267 {}
268
269 static struct arm_input_ops arm_tsc_ops_omap3 = {
270     .get_info           = tsc_get_info,
271     .probe              = tsc_probe,
272     .attach             = tsc_attach,
273     .enable             = tsc_enable,
274     .disable            = tsc_disable,
275 };
276
277 arm_input_register(&arm_tsc_ops_omap3);