6 #include <pthread-l4.h>
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>
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>
25 #include "tsc-omap3.h"
33 Tsc_coord ul; // upper left coordinate
34 Tsc_coord lr; // lower right coordinate
37 static int get_width(Tsc_disp *d)
38 { return d->lr.x - d->ul.x; }
40 static int get_height(Tsc_disp *d)
41 { return d->lr.y - d->ul.y; }
43 static int is_valid(Tsc_disp *d, int x, int y)
45 if ((x >= d->ul.x) && (x <= d->lr.x) &&
46 (y >= d->ul.y) && (y <= d->lr.y))
52 static char *omap_dev_name = "OMAP_TSC";
54 static Input_handler tsc_handler;
55 static void *tsc_priv;
56 static pthread_t _pthread;
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
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 }};
70 static int tsc_init(void)
72 vbus = l4re_get_env_cap("vbus");
74 if (l4_is_invalid_cap(vbus))
76 printf("Failed to query vbus\n");
80 if (l4vbus_get_device_by_hid(vbus, 0, &tsc_handle, omap_dev_name, 0, 0))
82 printf("[TSC] Cannot find TSC device\n");
86 if (l4vbus_get_device_by_hid(vbus, 0, &gpio_handle, "gpio", 0, 0))
88 printf("[TSC] Cannot find GPIO bus\n");
92 if (l4vbus_get_device_by_hid(vbus, 0, &mcspi_handle, "mcspi", 0, 0))
94 printf("[TSC] Cannot find McSPI bus\n");
102 static void tsc_get_pen_position(int *x, int *y)
104 l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
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);
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;
117 static void tsc_get_pen_position(int *x, int *y)
119 l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
121 l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
122 l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data1);
124 l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0xd300);
125 l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data2);
127 l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x9300);
128 l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data3);
130 l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
131 l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data4);
133 *x = ((data2 & 0x7f) << 5) | ((data3 & 0xf800) >> 11);
134 *y = ((data3 & 0x7f) << 5) | ((data4 & 0xf800) >> 11);
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;
140 //printf ("[TSC] Info: (x,y)=(%d,%d)\n", *x, *y);
143 l4_cap_idx_t get_icu(void);
145 static void create_motion_event(void)
148 tsc_get_pen_position(&x, &y);
149 if (is_valid(&disp_virt, x, y))
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);
158 static int tsc_irq_func(void)
160 l4_cap_idx_t irq_cap = l4re_util_cap_alloc();
161 l4_cap_idx_t thread_cap = pthread_getl4cap(_pthread);
164 l4_debugger_set_object_name(thread_cap, "tsc-omap3.irq");
167 if (l4io_request_irq2(irq, irq_cap, L4_IRQ_F_NEG_EDGE) < 0)
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()))
178 tag = l4_irq_receive(irq_cap, L4_IPC_NEVER);
179 if (l4_ipc_error(tag, l4_utcb()))
181 printf("[TSC] Error: Receive irq failed\n");
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);
194 if (l4vbus_gpio_read(vbus, gpio_handle, irq, &pen_up))
198 create_motion_event();
201 if (l4vbus_gpio_read(vbus, gpio_handle, irq, &pen_up))
205 // generate touch end event;
206 Input_event ev2 = { L4RE_EV_KEY, L4RE_BTN_LEFT, 0 };
207 tsc_handler(ev2, tsc_priv);
210 l4_umword_t label = 0;
211 l4_icu_unmask(get_icu(), irq, &label, L4_IPC_NEVER);
216 static void* __irq_func(void *data)
219 int ret = tsc_irq_func();
220 printf("[TSC] Warning: irq handler returned with:%d\n", ret);
224 static const char *tsc_get_info(void)
225 { return "ARM OMAP3EVM TSC"; }
227 static int tsc_probe(const char *name)
229 if (strcmp(omap_dev_name, name)) {
230 printf("[TSC] I'm not the right driver for [%s]\n", name);
233 return !l4io_lookup_device(omap_dev_name, NULL, 0, 0);
236 static void tsc_attach(Input_handler handler, void *priv)
238 tsc_handler = handler;
240 pthread_attr_t thread_attr;
243 if ((err = pthread_attr_init(&thread_attr)) != 0)
244 printf("[TSC] Error: Initializing pthread attr: %d", err);
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);
252 err = pthread_create(&_pthread, &thread_attr, __irq_func, 0);
254 printf("[TSC] Error: Creating thread");
257 static void tsc_enable(void)
261 printf("[TSC] Init failed!\n");
266 static void tsc_disable(void)
269 static struct arm_input_ops arm_tsc_ops_omap3 = {
270 .get_info = tsc_get_info,
272 .attach = tsc_attach,
273 .enable = tsc_enable,
274 .disable = tsc_disable,
277 arm_input_register(&arm_tsc_ops_omap3);