2 #include "pvr_events.h"
3 #include "servicesint.h"
4 #include "sgx_bridge.h"
6 #include "pvr_bridge_km.h"
7 #include "pvr_trace_cmd.h"
9 #include <linux/wait.h>
10 #include <linux/sched.h>
11 #include <linux/spinlock.h>
12 #include <linux/time.h>
13 #include <linux/uaccess.h>
15 #include <linux/notifier.h>
16 #include <linux/slab.h>
18 #include <plat/display.h>
20 static spinlock_t event_lock;
21 static struct list_head sync_wait_list;
22 static struct list_head flip_wait_list;
23 static struct notifier_block dss_nb;
25 static inline bool is_render_complete(const struct PVRSRV_SYNC_DATA *sync,
26 u32 write_ops_pending)
28 return (int)sync->ui32WriteOpsComplete - (int)write_ops_pending >= 0;
31 static void pvr_signal_sync_event(struct pvr_pending_sync_event *e,
32 const struct timeval *now)
34 e->event.tv_sec = now->tv_sec;
35 e->event.tv_usec = now->tv_usec;
37 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
39 wake_up_interruptible(&e->base.file_priv->event_wait);
42 int pvr_sync_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
43 const struct PVRSRV_KERNEL_SYNC_INFO *sync_info,
46 struct pvr_pending_sync_event *e;
50 e = kzalloc(sizeof(*e), GFP_KERNEL);
54 e->event.base.type = PVR_EVENT_SYNC;
55 e->event.base.length = sizeof(e->event);
56 e->event.sync_info = sync_info;
57 e->event.user_data = user_data;
58 e->base.event = &e->event.base;
59 e->base.file_priv = priv;
60 e->base.destroy = (void (*)(struct pvr_pending_event *))kfree;
61 e->base.write_ops_pending = sync_info->psSyncData->ui32WriteOpsPending;
63 do_gettimeofday(&now);
64 spin_lock_irqsave(&event_lock, flags);
66 if (priv->event_space < sizeof(e->event)) {
67 spin_unlock_irqrestore(&event_lock, flags);
72 priv->event_space -= sizeof(e->event);
74 list_add_tail(&e->base.link, &sync_wait_list);
75 if (is_render_complete(sync_info->psSyncData,
76 e->base.write_ops_pending))
77 pvr_signal_sync_event(e, &now);
79 spin_unlock_irqrestore(&event_lock, flags);
84 static void pvr_signal_flip_event(struct pvr_pending_flip_event *e,
85 const struct timeval *now)
87 e->event.tv_sec = now->tv_sec;
88 e->event.tv_usec = now->tv_usec;
90 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
92 wake_up_interruptible(&e->base.file_priv->event_wait);
95 int pvr_flip_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
97 enum pvr_sync_wait_seq_type type, u64 user_data)
100 struct pvr_pending_flip_event *e;
104 e = kzalloc(sizeof(*e), GFP_KERNEL);
109 case _PVR_SYNC_WAIT_FLIP:
110 e->event.base.type = PVR_EVENT_FLIP;
111 e->dss_event = OMAP_DSS_NOTIFY_GO_OVL;
113 case _PVR_SYNC_WAIT_UPDATE:
114 e->event.base.type = PVR_EVENT_UPDATE;
115 e->dss_event = OMAP_DSS_NOTIFY_UPDATE_OVL;
120 e->event.base.length = sizeof(e->event);
121 e->base.event = &e->event.base;
122 e->event.overlay = overlay;
123 e->event.user_data = user_data;
124 e->base.file_priv = priv;
125 e->base.destroy = (void (*)(struct pvr_pending_event *))kfree;
127 do_gettimeofday(&now);
128 spin_lock_irqsave(&event_lock, flags);
130 if (priv->event_space < sizeof(e->event)) {
131 spin_unlock_irqrestore(&event_lock, flags);
136 priv->event_space -= sizeof(e->event);
138 list_add_tail(&e->base.link, &flip_wait_list);
140 spin_unlock_irqrestore(&event_lock, flags);
142 return omap_dss_request_notify(e->dss_event, overlay);
148 static bool pvr_dequeue_event(struct PVRSRV_FILE_PRIVATE_DATA *priv,
149 size_t total, size_t max, struct pvr_pending_event **out)
151 struct pvr_pending_event *e;
155 spin_lock_irqsave(&event_lock, flags);
158 if (list_empty(&priv->event_list))
161 e = list_first_entry(&priv->event_list, struct pvr_pending_event, link);
162 if (e->event->length + total > max)
165 priv->event_space += e->event->length;
171 spin_unlock_irqrestore(&event_lock, flags);
176 static void trace_pvr_event(struct pvr_pending_event *e)
178 struct PVRSRV_PER_PROCESS_DATA *proc;
180 proc = e->file_priv->proc;
183 switch (e->event->type) {
186 struct pvr_event_sync *evsync;
187 struct pvr_trcmd_syn *ts;
189 evsync = (struct pvr_event_sync *)e->event;
190 ts = pvr_trcmd_alloc(PVR_TRCMD_SGX_QBLT_SYNCOMP,
191 proc->ui32PID, proc->name, sizeof(*ts));
192 pvr_trcmd_set_syn(ts, evsync->sync_info);
196 pvr_trcmd_alloc(PVR_TRCMD_SGX_QBLT_FLPCOMP,
197 proc->ui32PID, proc->name, 0);
199 case PVR_EVENT_UPDATE:
200 pvr_trcmd_alloc(PVR_TRCMD_SGX_QBLT_UPDCOMP,
201 proc->ui32PID, proc->name, 0);
210 ssize_t pvr_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
212 struct PVRSRV_FILE_PRIVATE_DATA *priv = filp->private_data;
213 struct pvr_pending_event *e;
217 ret = wait_event_interruptible(priv->event_wait,
218 !list_empty(&priv->event_list));
224 while (pvr_dequeue_event(priv, total, count, &e)) {
225 if (copy_to_user(buf + total, e->event, e->event->length)) {
232 total += e->event->length;
239 unsigned int pvr_poll(struct file *filp, struct poll_table_struct *wait)
241 struct PVRSRV_FILE_PRIVATE_DATA *priv = filp->private_data;
242 unsigned int mask = 0;
244 poll_wait(filp, &priv->event_wait, wait);
246 if (!list_empty(&priv->event_list))
247 mask |= POLLIN | POLLRDNORM;
252 void pvr_handle_sync_events(void)
254 struct pvr_pending_sync_event *e;
255 struct pvr_pending_sync_event *t;
259 do_gettimeofday(&now);
261 spin_lock_irqsave(&event_lock, flags);
263 list_for_each_entry_safe(e, t, &sync_wait_list, base.link) {
264 if (!is_render_complete(e->event.sync_info->psSyncData,
265 e->base.write_ops_pending))
268 pvr_signal_sync_event(e, &now);
271 spin_unlock_irqrestore(&event_lock, flags);
274 static int dss_notifier_callback(struct notifier_block *nb,
275 unsigned long event, void *data)
277 struct pvr_pending_flip_event *e;
278 struct pvr_pending_flip_event *t;
281 long overlay = (long) data;
283 do_gettimeofday(&now);
285 spin_lock_irqsave(&event_lock, flags);
287 list_for_each_entry_safe(e, t, &flip_wait_list, base.link) {
288 if (!(e->dss_event & event))
290 if (e->event.overlay != overlay)
293 pvr_signal_flip_event(e, &now);
296 spin_unlock_irqrestore(&event_lock, flags);
301 void pvr_release_events(struct PVRSRV_FILE_PRIVATE_DATA *priv)
303 struct pvr_pending_event *w;
304 struct pvr_pending_event *z;
305 struct pvr_pending_sync_event *e;
306 struct pvr_pending_sync_event *t;
307 struct pvr_pending_flip_event *e2;
308 struct pvr_pending_flip_event *t2;
311 spin_lock_irqsave(&event_lock, flags);
313 /* Remove pending waits */
314 list_for_each_entry_safe(e, t, &sync_wait_list, base.link)
315 if (e->base.file_priv == priv) {
316 list_del(&e->base.link);
317 e->base.destroy(&e->base);
320 list_for_each_entry_safe(e2, t2, &flip_wait_list, base.link)
321 if (e2->base.file_priv == priv) {
322 list_del(&e2->base.link);
323 e2->base.destroy(&e2->base);
326 /* Remove unconsumed events */
327 list_for_each_entry_safe(w, z, &priv->event_list, link)
330 spin_unlock_irqrestore(&event_lock, flags);
333 void pvr_init_events(void)
335 spin_lock_init(&event_lock);
336 INIT_LIST_HEAD(&sync_wait_list);
337 INIT_LIST_HEAD(&flip_wait_list);
339 dss_nb.notifier_call = dss_notifier_callback;
340 // omap_dss_register_notifier(&dss_nb);
343 void pvr_exit_events(void)
345 // omap_dss_unregister_notifier(&dss_nb);