~gma500/emgd/trunk

« back to all changes in this revision

Viewing changes to emgd-dkms-1.5.15.2856/emgd/include/plb/cmd.h

  • Committer: José Bernardo Bandos
  • Date: 2010-08-28 16:04:10 UTC
  • Revision ID: jbs@jbs-laptop-20100828160410-nw5zohdn37oupdv2
First step to add emgd drivers from meego

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- pse-c -*-
 
2
 *-----------------------------------------------------------------------------
 
3
 * Filename: cmd.h
 
4
 * $Revision: 1.5 $
 
5
 *-----------------------------------------------------------------------------
 
6
 * Copyright © 2002-2010, Intel Corporation.
 
7
 *  
 
8
 * This program is free software; you can redistribute it and/or modify it
 
9
 * under the terms and conditions of the GNU General Public License,
 
10
 * version 2, as published by the Free Software Foundation.
 
11
 * 
 
12
 * This program is distributed in the hope it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
15
 * more details.
 
16
 * 
 
17
 * You should have received a copy of the GNU General Public License along with
 
18
 * this program; if not, write to the Free Software Foundation, Inc., 
 
19
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *-----------------------------------------------------------------------------
 
21
 * Description:
 
22
 *  Device dependent header file for the command interface for poulsbo
 
23
 *  devices.
 
24
 *-----------------------------------------------------------------------------
 
25
 */
 
26
 
 
27
#ifndef _PLB_CMD_H
 
28
#define _PLB_CMD_H
 
29
 
 
30
#include <io.h>
 
31
#include <sched.h>
 
32
 
 
33
#include <instr_common.h>
 
34
#include <utils.h>
 
35
 
 
36
//#define TMP_PLB_SERIALIZE_2D
 
37
//#define TMP_PLB_SERIALIZE_RASTER
 
38
//#define TMP_PLB_SERIALIZE_BINNER
 
39
#define CONFIG_ENABLE_SYNC_SLEEP 0
 
40
#define CONFIG_ENABLE_CPU_SYNC 0
 
41
#define CONFIG_ENABLE_DIRECT_2D 1
 
42
#define CONFIG_ENABLE_DIRECT_BIN 1
 
43
#define CONFIG_ENABLE_DIRECT_VIDEO 1
 
44
 
 
45
 
 
46
#define CMD_QUEUE_SIZE_PLB (1024*128)
 
47
#define MAX_2D_COMMAND_PLB 0x60
 
48
 
 
49
/* Wait at most 2 second for a 2D, 3D, or Video operation to complete */
 
50
#define CMD_TIMEOUT_PLB 2000
 
51
 
 
52
/*
 
53
 * Bitfield to track which engines are possibly busy and in need
 
54
 * of sync.
 
55
 */
 
56
#define CMD_ENGINE_2D_PLB     0x01
 
57
#define CMD_ENGINE_BINNER_PLB 0x02
 
58
#define CMD_ENGINE_RASTER_PLB 0x04
 
59
#define CMD_ENGINE_VIDEO_PLB  0x08
 
60
#define CMD_ENGINE_CPU_PLB    0x10
 
61
#define CMD_ENGINE_WAIT_PLB   0x20
 
62
#define CMD_ENGINE_DPM_PLB    0x40
 
63
#define CMD_ENGINE_ALL_PLB    0x7f
 
64
 
 
65
typedef unsigned long cmd_engine_plb_t;
 
66
 
 
67
/*
 
68
 * Virtual Commands for the PLB Virtual Engine.
 
69
 * Note: They are numbered such that they are unlikely to happen in
 
70
 * a command stream and should then be easily spotted during debug.
 
71
 *
 
72
 * There is a special relationship between the 3D and RASTER numbers.
 
73
 * The command packet for these two is the same and the command is either
 
74
 * a binner + raster (3D) or just a raster alone (RASTER).
 
75
 * Sometimes the binner is processed out of order and the command ID is
 
76
 * converted from 3D to raster by or'ing in the extra bit.
 
77
 */
 
78
#define VCOMMAND_2D_PLB          0x12300000
 
79
#define VCOMMAND_3D_PLB          0x12310000
 
80
#define VCOMMAND_RASTER_PLB      0x12330000
 
81
#define VCOMMAND_VIDEO_PLB       0x12340000
 
82
#define VCOMMAND_REG_PLB         0x12350000
 
83
#define VCOMMAND_WAIT_PLB        0x12360000
 
84
#define VCOMMAND_SYNC_PLB        0x12370000
 
85
#define VCOMMAND_SW2D_PLB        0x12380000
 
86
#define VCOMMAND_EXIT_PLB        0x123e0000
 
87
#define VCOMMAND_WRAP_PLB        0x123f0000
 
88
#define VCOMMAND_ID_MASK_PLB     0xffff0000
 
89
#define VCOMMAND_SIZE_MASK_PLB   0x0000ffff
 
90
 
 
91
#define CMD_SYNC_NEED_IDLE_PLB (CMD_ENGINE_RASTER_PLB | CMD_ENGINE_DPM_PLB | \
 
92
                CMD_ENGINE_VIDEO_PLB | CMD_ENGINE_WAIT_PLB | CMD_ENGINE_2D_PLB)
 
93
 
 
94
#define CMD_2D_NEED_IDLE_PLB (CMD_ENGINE_RASTER_PLB | \
 
95
                CMD_ENGINE_VIDEO_PLB | CMD_ENGINE_WAIT_PLB)
 
96
 
 
97
#define CMD_BINNER_NEED_IDLE_PLB (CMD_ENGINE_BINNER_PLB | CMD_ENGINE_2D_PLB)
 
98
 
 
99
#define CMD_RASTER_NEED_IDLE_PLB (CMD_ENGINE_2D_PLB | CMD_ENGINE_VIDEO_PLB | \
 
100
                CMD_ENGINE_BINNER_PLB | CMD_ENGINE_RASTER_PLB | CMD_ENGINE_DPM_PLB | \
 
101
                CMD_ENGINE_WAIT_PLB)
 
102
 
 
103
#define CMD_VIDEO_NEED_IDLE_PLB (CMD_ENGINE_WAIT_PLB)
 
104
 
 
105
#define CMD_REG_NEED_IDLE_PLB (CMD_ENGINE_RASTER_PLB | CMD_ENGINE_DPM_PLB | \
 
106
                CMD_ENGINE_2D_PLB | CMD_ENGINE_VIDEO_PLB | CMD_ENGINE_WAIT_PLB)
 
107
 
 
108
#define CMD_CPU_NEED_IDLE_PLB (CMD_ENGINE_RASTER_PLB | CMD_ENGINE_DPM_PLB | \
 
109
                CMD_ENGINE_2D_PLB | CMD_ENGINE_VIDEO_PLB | CMD_ENGINE_WAIT_PLB)
 
110
 
 
111
#define CMD_WAIT_NEED_IDLE_PLB (CMD_ENGINE_WAIT_PLB)
 
112
 
 
113
/*
 
114
 * wait_flags
 
115
 * Flags to pass with the VCOMMAND_WAIT_PLB commands
 
116
 */
 
117
/*#define CMD_WAIT_VBLANK_PLB   1*/
 
118
/*#define CMD_WAIT_SCANLINE_PLB 2*/
 
119
#define CMD_WAIT_FLIP_A_PLB   4
 
120
#define CMD_WAIT_FLIP_B_PLB   8
 
121
#define CMD_WAIT_OVL_PLB      0x10
 
122
#define CMD_WAIT_OVL2_PLB     0x20
 
123
#define CMD_WAIT_VIDEO_SYNC_PLB 0x40
 
124
 
 
125
#define CMD_SW2D_SRC_COPY_BLT   1
 
126
 
 
127
typedef struct _cmd_queue_plb {
 
128
        /* 2D HW access */
 
129
        struct {
 
130
                unsigned char *avail_reg;
 
131
                unsigned char *status_reg;
 
132
                igd_command_t *base;
 
133
                igd_command_t *end;
 
134
                volatile unsigned int avail;
 
135
        } blt;
 
136
 
 
137
        /* Registers - Set at init*/
 
138
        unsigned char *event_status_reg;
 
139
        unsigned char *event_enable_reg;
 
140
        unsigned char *event_clear_reg;
 
141
        unsigned char *event_status2_reg;
 
142
        unsigned char *event_enable2_reg;
 
143
        unsigned char *event_clear2_reg;
 
144
        unsigned char *mtx_status_reg;
 
145
        unsigned long msvdx_fence;
 
146
        unsigned long msvdx_last_fence;
 
147
        /* HW status page virtual addr */
 
148
        volatile unsigned char *sync;
 
149
 
 
150
        /* Virtual command queue - accessed by both threads */
 
151
        volatile igd_command_t vqueue[CMD_QUEUE_SIZE_PLB];
 
152
        volatile igd_command_t * volatile head;
 
153
        volatile igd_command_t * volatile tail;
 
154
        volatile igd_command_t * current_node;
 
155
        volatile igd_command_t * reservation;
 
156
 
 
157
        /* Only for main thread */
 
158
        unsigned long last_sync;
 
159
 
 
160
        /* Check lock */
 
161
        volatile igd_command_t * volatile last_head_value;
 
162
        volatile os_alarm_t last_head_time;
 
163
 
 
164
        /* Process thread */
 
165
 
 
166
        /* Accessed by both main thread and process thread */
 
167
        unsigned long wait_flags;
 
168
        volatile cmd_engine_plb_t busy_engines;
 
169
 
 
170
        igd_appcontext_h appcontext;
 
171
        struct _igd_context *context;
 
172
 
 
173
        /* Flag used by the main thread in cmd_reserve when
 
174
         * a 2d instruction is being written directly into
 
175
         * the hardware.
 
176
         * Can only be set if is_thread_waiting = 1.
 
177
         * Purpose is for update to know this is a 2d instr
 
178
         * directly to the HW.
 
179
         */
 
180
        int direct_access_2d;
 
181
 
 
182
        /* Mutex/Conditions */
 
183
        /* The process thread will set this to 1 when it is
 
184
         * sleeping and the main thread will set to 0 when awake
 
185
         */
 
186
        volatile int is_thread_waiting;
 
187
        os_pthread_mutex_t thread_mutex;
 
188
        os_pthread_cond_t  thread_waiting;
 
189
 
 
190
        /*
 
191
         * The main thread will sleep on the sync_waiting condition variable
 
192
         * when waiting for a sync tom complete. The sync_waiting_id will
 
193
         * identify the sync number that the main thread is waiting for.
 
194
         */
 
195
        volatile unsigned long sync_waiting_id;
 
196
        volatile int sync_thread_waiting;
 
197
        os_pthread_cond_t sync_waiting_cond;
 
198
 
 
199
        /* This protects main thread and process thread when calling
 
200
         * check_lock_plb.
 
201
         */
 
202
        os_pthread_mutex_t check_lock_mutex;
 
203
} cmd_queue_plb_t;
 
204
 
 
205
#if 0  /* Removing all the command vqueue stuff */
 
206
extern os_pthread_t *cmd_vqueue_thread_plb;
 
207
extern void *process_vqueue_plb(void *data);
 
208
 
 
209
#define CMD_GET_QUEUE_PLB(d, p) \
 
210
        ((cmd_queue_plb_t *)((igd_display_pipe_t *)                     \
 
211
                ((igd_display_context_t *)d)->pipe)->queue[p])
 
212
 
 
213
/*
 
214
 * This is a clever trick so that we get inlined functions for normal
 
215
 * builds and a single instance of this function for debug builds.
 
216
 */
 
217
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
 
218
OPT_DEBUG_INLINE int cmd_reserve_plb(cmd_queue_plb_t *queue,
 
219
        unsigned long size,
 
220
        igd_command_t type)
 
221
{
 
222
        volatile igd_command_t *needed_start;
 
223
        volatile igd_command_t *needed_end;
 
224
        int first = 1;
 
225
        int expired = 0;
 
226
//      int wrap = 0;
 
227
        os_alarm_t timeout = (os_alarm_t)0;
 
228
 
 
229
        OS_TRACE_ENTER;
 
230
 
 
231
        /* Since this is not a 2d instruction, ensure update knows this */
 
232
        queue->direct_access_2d = 0;
 
233
 
 
234
        /*
 
235
         * Always leave space for 1 extra command so that we can put
 
236
         * the wrap command in without waiting on the head. Also remember
 
237
         * to leave space at the end of the queue.
 
238
         */
 
239
        needed_start = queue->tail;
 
240
        needed_end = queue->tail + size + 2;
 
241
        if(needed_end >= &queue->vqueue[CMD_QUEUE_SIZE_PLB]) {
 
242
                /* Doesn't fit so wrap to beginning */
 
243
                needed_start = queue->vqueue;
 
244
                needed_end = queue->vqueue + size + 2;
 
245
                *queue->tail = VCOMMAND_WRAP_PLB;
 
246
                //wrap = 0;
 
247
        }
 
248
 
 
249
        while(1) {
 
250
                if((queue->head <= needed_start) ||
 
251
                        (queue->head >= needed_end)) {
 
252
                        //if(wrap) {
 
253
                        //      queue->tail = queue->vqueue;
 
254
                        //}
 
255
                        *needed_start++ = type | size;
 
256
                        queue->current_node = needed_start;
 
257
                        queue->reservation = needed_start + size;
 
258
                        OS_TRACE_EXIT;
 
259
                        return 0;
 
260
                }
 
261
                if(first) {
 
262
                        timeout = OS_SET_ALARM(CMD_TIMEOUT_PLB);
 
263
                        first = 0;
 
264
                }
 
265
                if(expired) {
 
266
                        break;
 
267
                }
 
268
                OS_SCHEDULE();
 
269
                expired = OS_TEST_ALARM(timeout);
 
270
        }
 
271
 
 
272
        OS_ERROR_EXIT("Timeout waiting for Virtual Queue Space");
 
273
        return -IGD_ERROR_BUSY;
 
274
}
 
275
#else
 
276
extern int cmd_reserve_plb(cmd_queue_plb_t *queue,
 
277
        unsigned long size, igd_command_t type);
 
278
#endif
 
279
 
 
280
extern int cmd_ready_plb(cmd_queue_plb_t *queue, cmd_engine_plb_t need_idle);
 
281
 
 
282
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
 
283
OPT_DEBUG_INLINE int cmd_update_plb(cmd_queue_plb_t *queue)
 
284
{
 
285
        int ret;
 
286
 
 
287
        OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
 
288
        OS_ASSERT(queue->current_node <= queue->reservation,
 
289
                "Queue use exceeds reservation", -IGD_ERROR_INVAL);
 
290
 
 
291
        /*
 
292
         * If the queue is set up for direct access then fire off the
 
293
         * blit engine and return.
 
294
         */
 
295
        if(queue->direct_access_2d) {
 
296
                unsigned int tmp;
 
297
                /*
 
298
                 * Need to read the last dword back to trigger the blit engine.
 
299
                 */
 
300
                tmp = OS_READ32(queue->blt.end - 1);
 
301
                queue->current_node = NULL;
 
302
                queue->reservation = NULL;
 
303
 
 
304
#ifdef TMP_PLB_SERIALIZE_2D
 
305
                cmd_ready_plb(queue, CMD_CPU_NEED_IDLE_PLB);
 
306
#endif
 
307
 
 
308
                OS_TRACE_EXIT;
 
309
                return 0;
 
310
        }
 
311
 
 
312
 
 
313
        /*
 
314
         * Commands were placed in the ring so move the tail. Then if we
 
315
         * have threads signal the ring thread to go. If we don't have
 
316
         * threads we will just process the commands that were placed in the
 
317
         * ring.
 
318
         */
 
319
        ret = OS_PTHREAD_MUTEX_LOCK(&queue->thread_mutex);
 
320
        queue->tail = queue->current_node;
 
321
 
 
322
        /*
 
323
         * Null these out so that any invalid uses will get caught
 
324
         */
 
325
        queue->current_node = NULL;
 
326
        queue->reservation = NULL;
 
327
 
 
328
        if(cmd_vqueue_thread_plb) {
 
329
                        queue->is_thread_waiting = 0;
 
330
                ret = OS_PTHREAD_COND_SIGNAL(&queue->thread_waiting);
 
331
                OS_PTHREAD_MUTEX_UNLOCK(&queue->thread_mutex);
 
332
        } else {
 
333
                OS_PTHREAD_MUTEX_UNLOCK(&queue->thread_mutex);
 
334
                /* For syncronous use */
 
335
                process_vqueue_plb(queue);
 
336
        }
 
337
 
 
338
        return 0;
 
339
}
 
340
#else
 
341
extern int cmd_update_plb(cmd_queue_plb_t *queue);
 
342
#endif
 
343
 
 
344
/*
 
345
 * 2D Engine has a on-chip queue. As long as there is space
 
346
 * in the queue the 2d commands can be written starting at the
 
347
 * base register.
 
348
 *
 
349
 * 2D Engine runs asynchronously with other engines so for IEGD
 
350
 * we ensure that other engines are idle when inserting 2d commands.
 
351
 */
 
352
static __inline int cmd_2d_direct_reserve_plb(cmd_queue_plb_t *queue,
 
353
        unsigned int size)
 
354
{
 
355
        int ret;
 
356
        os_alarm_t timeout = (os_alarm_t)0;
 
357
        int expired = 0;
 
358
        int first = 1;
 
359
 
 
360
        OS_TRACE_ENTER;
 
361
        OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
 
362
        OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
 
363
                -IGD_ERROR_INVAL);
 
364
 
 
365
        queue->direct_access_2d = 1;
 
366
 
 
367
        if(queue->busy_engines & CMD_2D_NEED_IDLE_PLB) {
 
368
                ret = cmd_ready_plb(queue, CMD_2D_NEED_IDLE_PLB);
 
369
                /* Do not return if cmd_ready_plb returns an error.
 
370
                 * this may be a sync and not putting it in the command queue
 
371
                 * will cause problems.  Since the failure was on a previous
 
372
                 * command, this should be ok.
 
373
                if(ret) {
 
374
                        return ret;
 
375
                }*/
 
376
        }
 
377
 
 
378
        queue->busy_engines |= CMD_ENGINE_2D_PLB;
 
379
 
 
380
        queue->current_node = queue->blt.base;
 
381
        queue->blt.end = queue->blt.base + size;
 
382
        queue->reservation = queue->blt.end;
 
383
        if (size <= queue->blt.avail) {
 
384
                queue->blt.avail -= size;
 
385
                OS_TRACE_EXIT;
 
386
                return 0;
 
387
        }
 
388
        while(1) {
 
389
                queue->blt.avail = OS_READ32(queue->blt.avail_reg);
 
390
                if(size <= queue->blt.avail) {
 
391
                        break;
 
392
                }
 
393
                if(first) {
 
394
                        timeout = OS_SET_ALARM(CMD_TIMEOUT_PLB);
 
395
                        first = 0;
 
396
                }
 
397
                if(expired) {
 
398
                        OS_ERROR_EXIT("Timeout waiting for 2D Hardware");
 
399
                        return -IGD_ERROR_HWERROR;
 
400
                }
 
401
                expired = OS_TEST_ALARM(timeout);
 
402
        }
 
403
        queue->blt.avail -= size;
 
404
 
 
405
        OS_TRACE_EXIT;
 
406
        return 0;
 
407
}
 
408
 
 
409
/*
 
410
 * Reserve Space for a 2D command. This function will set up the
 
411
 * queue to directly send the 2d command to the hardware when there
 
412
 * are no engines to wait for and will instead set up the queue to
 
413
 * put the 2d command in the virtual ring buffer when we would
 
414
 * have to wait.
 
415
 * In this manner we get the benefit of direct command placement
 
416
 * with 0 latency when we can use it and non-blocking behavior
 
417
 * always.
 
418
 */
 
419
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
 
420
OPT_DEBUG_INLINE int cmd_2d_reserve_plb(cmd_queue_plb_t *queue,
 
421
        unsigned int size)
 
422
{
 
423
        int ret;
 
424
 
 
425
        OS_TRACE_ENTER;
 
426
        OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
 
427
        OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
 
428
                -IGD_ERROR_INVAL);
 
429
 
 
430
        /*
 
431
         * Only do a direct reserve of the 2D command if the virtual queue
 
432
         * is empty AND this won't have to wait for another engine
 
433
         * to complete.  Otherwise this stalls waiting on that engine.
 
434
         */
 
435
        if(CONFIG_ENABLE_DIRECT_2D && (queue->is_thread_waiting == 1) &&
 
436
                        !(queue->busy_engines & CMD_2D_NEED_IDLE_PLB)) {
 
437
                ret = cmd_2d_direct_reserve_plb(queue, size);
 
438
                OS_TRACE_EXIT;
 
439
                return ret;
 
440
        }
 
441
 
 
442
        ret = cmd_reserve_plb(queue, size, VCOMMAND_2D_PLB);
 
443
        OS_TRACE_EXIT;
 
444
        return ret;
 
445
}
 
446
#else
 
447
extern int cmd_2d_reserve_plb(cmd_queue_plb_t *queue,
 
448
        unsigned int size);
 
449
#endif
 
450
 
 
451
#define CMD_2D_RESERVE_PLB(q, s) cmd_2d_reserve_plb(q, s)
 
452
#define CMD_2D_WRITE_PLB(q, dw) INSTR_WRITE(dw, q->current_node)
 
453
#define CMD_2D_UPDATE_PLB(q) cmd_update_plb(q)
 
454
 
 
455
 
 
456
/*
 
457
 * The sync command uses the 2D engine directly when there are no
 
458
 * dependent engines running. Otherwise it puts a sync command in the
 
459
 * vqueue which is processed using the CPU in the cmd thread.
 
460
 */
 
461
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
 
462
OPT_DEBUG_INLINE int cmd_sync_reserve_plb(cmd_queue_plb_t *queue,
 
463
        unsigned int size)
 
464
{
 
465
        int ret;
 
466
 
 
467
        OS_TRACE_ENTER;
 
468
        OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
 
469
        OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
 
470
                -IGD_ERROR_INVAL);
 
471
 
 
472
        /*
 
473
         * Only do a direct reserve of the sync if the virtual queue
 
474
         * is empty AND this won't have to wait for another engine
 
475
         * to complete.  Otherwise this stalls waiting on that engine.
 
476
         */
 
477
        if((queue->is_thread_waiting == 1) &&
 
478
                        !(queue->busy_engines & CMD_2D_NEED_IDLE_PLB)) {
 
479
                ret = cmd_2d_direct_reserve_plb(queue, size);
 
480
                OS_TRACE_EXIT;
 
481
                return ret;
 
482
        }
 
483
 
 
484
        ret = cmd_reserve_plb(queue, size, VCOMMAND_SYNC_PLB);
 
485
        OS_TRACE_EXIT;
 
486
        return ret;
 
487
}
 
488
#else
 
489
extern int cmd_sync_reserve_plb(cmd_queue_plb_t *queue);
 
490
#endif
 
491
 
 
492
#define CMD_SYNC_RESERVE_PLB(q, s) cmd_sync_reserve_plb(q, s)
 
493
#define CMD_SYNC_WRITE_PLB(q, dw) INSTR_WRITE(dw, q->current_node)
 
494
#define CMD_SYNC_UPDATE_PLB(q) cmd_update_plb(q)
 
495
#endif
 
496
 
 
497
 
 
498
#endif