2
*-----------------------------------------------------------------------------
5
*-----------------------------------------------------------------------------
6
* Copyright © 2002-2010, Intel Corporation.
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.
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
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
*-----------------------------------------------------------------------------
22
* Device dependent header file for the command interface for poulsbo
24
*-----------------------------------------------------------------------------
33
#include <instr_common.h>
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
46
#define CMD_QUEUE_SIZE_PLB (1024*128)
47
#define MAX_2D_COMMAND_PLB 0x60
49
/* Wait at most 2 second for a 2D, 3D, or Video operation to complete */
50
#define CMD_TIMEOUT_PLB 2000
53
* Bitfield to track which engines are possibly busy and in need
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
65
typedef unsigned long cmd_engine_plb_t;
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.
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.
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
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)
94
#define CMD_2D_NEED_IDLE_PLB (CMD_ENGINE_RASTER_PLB | \
95
CMD_ENGINE_VIDEO_PLB | CMD_ENGINE_WAIT_PLB)
97
#define CMD_BINNER_NEED_IDLE_PLB (CMD_ENGINE_BINNER_PLB | CMD_ENGINE_2D_PLB)
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 | \
103
#define CMD_VIDEO_NEED_IDLE_PLB (CMD_ENGINE_WAIT_PLB)
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)
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)
111
#define CMD_WAIT_NEED_IDLE_PLB (CMD_ENGINE_WAIT_PLB)
115
* Flags to pass with the VCOMMAND_WAIT_PLB commands
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
125
#define CMD_SW2D_SRC_COPY_BLT 1
127
typedef struct _cmd_queue_plb {
130
unsigned char *avail_reg;
131
unsigned char *status_reg;
134
volatile unsigned int avail;
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;
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;
157
/* Only for main thread */
158
unsigned long last_sync;
161
volatile igd_command_t * volatile last_head_value;
162
volatile os_alarm_t last_head_time;
166
/* Accessed by both main thread and process thread */
167
unsigned long wait_flags;
168
volatile cmd_engine_plb_t busy_engines;
170
igd_appcontext_h appcontext;
171
struct _igd_context *context;
173
/* Flag used by the main thread in cmd_reserve when
174
* a 2d instruction is being written directly into
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.
180
int direct_access_2d;
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
186
volatile int is_thread_waiting;
187
os_pthread_mutex_t thread_mutex;
188
os_pthread_cond_t thread_waiting;
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.
195
volatile unsigned long sync_waiting_id;
196
volatile int sync_thread_waiting;
197
os_pthread_cond_t sync_waiting_cond;
199
/* This protects main thread and process thread when calling
202
os_pthread_mutex_t check_lock_mutex;
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);
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])
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.
217
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
218
OPT_DEBUG_INLINE int cmd_reserve_plb(cmd_queue_plb_t *queue,
222
volatile igd_command_t *needed_start;
223
volatile igd_command_t *needed_end;
227
os_alarm_t timeout = (os_alarm_t)0;
231
/* Since this is not a 2d instruction, ensure update knows this */
232
queue->direct_access_2d = 0;
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.
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;
250
if((queue->head <= needed_start) ||
251
(queue->head >= needed_end)) {
253
// queue->tail = queue->vqueue;
255
*needed_start++ = type | size;
256
queue->current_node = needed_start;
257
queue->reservation = needed_start + size;
262
timeout = OS_SET_ALARM(CMD_TIMEOUT_PLB);
269
expired = OS_TEST_ALARM(timeout);
272
OS_ERROR_EXIT("Timeout waiting for Virtual Queue Space");
273
return -IGD_ERROR_BUSY;
276
extern int cmd_reserve_plb(cmd_queue_plb_t *queue,
277
unsigned long size, igd_command_t type);
280
extern int cmd_ready_plb(cmd_queue_plb_t *queue, cmd_engine_plb_t need_idle);
282
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
283
OPT_DEBUG_INLINE int cmd_update_plb(cmd_queue_plb_t *queue)
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);
292
* If the queue is set up for direct access then fire off the
293
* blit engine and return.
295
if(queue->direct_access_2d) {
298
* Need to read the last dword back to trigger the blit engine.
300
tmp = OS_READ32(queue->blt.end - 1);
301
queue->current_node = NULL;
302
queue->reservation = NULL;
304
#ifdef TMP_PLB_SERIALIZE_2D
305
cmd_ready_plb(queue, CMD_CPU_NEED_IDLE_PLB);
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
319
ret = OS_PTHREAD_MUTEX_LOCK(&queue->thread_mutex);
320
queue->tail = queue->current_node;
323
* Null these out so that any invalid uses will get caught
325
queue->current_node = NULL;
326
queue->reservation = NULL;
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);
333
OS_PTHREAD_MUTEX_UNLOCK(&queue->thread_mutex);
334
/* For syncronous use */
335
process_vqueue_plb(queue);
341
extern int cmd_update_plb(cmd_queue_plb_t *queue);
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
349
* 2D Engine runs asynchronously with other engines so for IEGD
350
* we ensure that other engines are idle when inserting 2d commands.
352
static __inline int cmd_2d_direct_reserve_plb(cmd_queue_plb_t *queue,
356
os_alarm_t timeout = (os_alarm_t)0;
361
OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
362
OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
365
queue->direct_access_2d = 1;
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.
378
queue->busy_engines |= CMD_ENGINE_2D_PLB;
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;
389
queue->blt.avail = OS_READ32(queue->blt.avail_reg);
390
if(size <= queue->blt.avail) {
394
timeout = OS_SET_ALARM(CMD_TIMEOUT_PLB);
398
OS_ERROR_EXIT("Timeout waiting for 2D Hardware");
399
return -IGD_ERROR_HWERROR;
401
expired = OS_TEST_ALARM(timeout);
403
queue->blt.avail -= size;
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
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
419
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
420
OPT_DEBUG_INLINE int cmd_2d_reserve_plb(cmd_queue_plb_t *queue,
426
OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
427
OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
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.
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);
442
ret = cmd_reserve_plb(queue, size, VCOMMAND_2D_PLB);
447
extern int cmd_2d_reserve_plb(cmd_queue_plb_t *queue,
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)
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.
461
#if !defined(CONFIG_DEBUG) || defined(IS_CMD_PLB_C)
462
OPT_DEBUG_INLINE int cmd_sync_reserve_plb(cmd_queue_plb_t *queue,
468
OS_ASSERT(queue, "Null Queue", -IGD_ERROR_INVAL);
469
OS_ASSERT( size < MAX_2D_COMMAND_PLB, "2D Command too large",
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.
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);
484
ret = cmd_reserve_plb(queue, size, VCOMMAND_SYNC_PLB);
489
extern int cmd_sync_reserve_plb(cmd_queue_plb_t *queue);
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)