~gma500/+junk/emgd152-natty

« back to all changes in this revision

Viewing changes to emgd-dkms-1.5.15.3082/emgd/video/msvdx/msvdx_init.c

  • Committer: Luca Forina
  • Date: 2011-02-06 15:11:54 UTC
  • Revision ID: luca.forina@gmail.com-20110206151154-9dzn5ugxjub9qenb
Upload Emgd 1.5.2 for Natty (override Maverick)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- pse-c -*-
 
2
 *-----------------------------------------------------------------------------
 
3
 * Filename: msvdx_init.c
 
4
 * $Revision: 1.23 $
 
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
 *-----------------------------------------------------------------------------
 
22
 * Description:
 
23
 *  Initialize the MSVDX video engine.  This loads the MTX firmware and
 
24
 *  starts a MTX thread running the firmware.
 
25
 *  The host communicates with the firmware via messages. The following
 
26
 *  messages are supported:
 
27
 *  INIT               -> MTX
 
28
 *  RENDER             -> MTX
 
29
 *  DEBLOCK            -> MTX
 
30
 *  BUBBLE             -> MTX
 
31
 *  TEST1              -> MTX
 
32
 *  TEST2              -> MTX
 
33
 *  CMD_COMPLETED      <- MTX
 
34
 *  CMD_COMPLTED_BATCH <- MTX
 
35
 *  DEBLOCK_REQUIRED   <- MTX
 
36
 *  TEST_RESPONSE      <- MTX
 
37
 *  ACK                <- MTX
 
38
 *  CMD_FAILED         <- MTX
 
39
 *-----------------------------------------------------------------------------
 
40
 */
 
41
 
 
42
#include <io.h>
 
43
#include <pci.h>
 
44
#include <memmap.h>
 
45
#include <sched.h>
 
46
 
 
47
#include <igd.h>
 
48
#include <igd_errno.h>
 
49
#include <igd_init.h>
 
50
 
 
51
#include <context.h>
 
52
#include <intelpci.h>
 
53
#include <general.h>
 
54
#include <utils.h>
 
55
#include <msvdx.h>
 
56
 
 
57
#include <plb/regs.h>
 
58
#include <plb/context.h>
 
59
#include <drm/drm.h>
 
60
#include <drm_emgd_private.h>
 
61
#include <emgd_drm.h>
 
62
 
 
63
 
 
64
struct drm_device *gpDrmDevice = NULL;
 
65
static int init_msvdx_first_time = 1;
 
66
 
 
67
extern void send_to_mtx(igd_context_t *context, unsigned long *init_msg);
 
68
extern int process_mtx_messages(igd_context_t *context,
 
69
                unsigned long *mtx_msgs, unsigned long mtx_msg_cnt,
 
70
                unsigned long fence);
 
71
 
 
72
extern void populate_fence_id(igd_context_t *context, unsigned long *mtx_msgs, 
 
73
                unsigned long mtx_msg_cnt);
 
74
extern int msvdx_dequeue_send(igd_context_t *context);
 
75
extern int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1, 
 
76
                                unsigned long size0, unsigned long size1);
 
77
 
 
78
static int poll_mtx_irq(igd_context_t *context);
 
79
static int reg_ready_psb(igd_context_t *context, unsigned long reg,
 
80
        unsigned long mask, unsigned long value);
 
81
static int context_count = 0;
 
82
 
 
83
void msvdx_reset_plb(igd_context_t *context);
 
84
 
 
85
static msvdx_fw_t *priv_fw = NULL;
 
86
 
 
87
extern unsigned long jiffies_at_last_dequeue;
 
88
 
 
89
 
 
90
int msvdx_query_plb(igd_context_t *context, 
 
91
                                        unsigned long *status)
 
92
{
 
93
        platform_context_plb_t *platform;
 
94
 
 
95
        EMGD_TRACE_ENTER;
 
96
 
 
97
        platform = (platform_context_plb_t *)context->platform_context;
 
98
        *status = 0;
 
99
 
 
100
        if (priv_fw) {
 
101
                *status |= VIDEO_STATE_FW_LOADED;
 
102
        }
 
103
 
 
104
        if(!platform->rendec_base0 || !platform->rendec_base1) {
 
105
                *status |= VIDEO_STATE_RENDEC_FREED;
 
106
        }
 
107
 
 
108
        EMGD_TRACE_EXIT;
 
109
        return 0;
 
110
}
 
111
 
 
112
int msvdx_pre_init_plb(struct drm_device *dev)
 
113
{
 
114
        EMGD_TRACE_ENTER;
 
115
 
 
116
    gpDrmDevice = dev;
 
117
 
 
118
        EMGD_TRACE_EXIT;
 
119
        return IGD_SUCCESS;
 
120
}
 
121
 
 
122
int msvdx_init_plb(unsigned long base0, unsigned long base1, 
 
123
                           void *msvdx_fw, unsigned long msvdx_fw_size)
 
124
{
 
125
    drm_emgd_private *priv;
 
126
    igd_context_t *context;
 
127
    unsigned char *mmio;
 
128
    unsigned long ram_bank;
 
129
    unsigned long bank_size;
 
130
    unsigned long current_bank;
 
131
    unsigned long address;
 
132
    unsigned long acc_control;
 
133
    unsigned long base_addr0, base_addr1, size0, size1;
 
134
    unsigned long ram_id;
 
135
    unsigned long ctrl;
 
136
    unsigned long i;
 
137
        unsigned long fw_size;
 
138
        unsigned long *fw_data;
 
139
        msvdx_fw_t *fw = NULL;
 
140
        platform_context_plb_t *platform = NULL;
 
141
 
 
142
        if (!priv_fw && msvdx_fw) {
 
143
                fw = (msvdx_fw_t *) msvdx_fw;        
 
144
                priv_fw = kzalloc(sizeof(msvdx_fw_t), GFP_KERNEL);
 
145
                priv_fw->fw_text_size = fw->fw_text_size;
 
146
                priv_fw->fw_data_size = fw->fw_data_size;
 
147
                priv_fw->fw_version_size = fw->fw_version_size;
 
148
                priv_fw->fw_data_location = fw->fw_data_location;
 
149
 
 
150
                fw_size = sizeof(unsigned long) * fw->fw_text_size;
 
151
                priv_fw->fw_text = kmalloc(fw_size, GFP_KERNEL);
 
152
                memcpy(priv_fw->fw_text, (void *) ((unsigned long) msvdx_fw) + 
 
153
                                ((unsigned long) fw->fw_text), fw_size);
 
154
 
 
155
                fw_size = sizeof(unsigned long) * fw->fw_data_size;
 
156
                priv_fw->fw_data = kmalloc(fw_size, GFP_KERNEL);
 
157
                memcpy(priv_fw->fw_data, (void *) ((unsigned long) msvdx_fw) + 
 
158
                        ((unsigned long) fw->fw_data), fw_size);
 
159
 
 
160
                priv_fw->fw_version = kzalloc(priv_fw->fw_version_size, GFP_KERNEL);
 
161
                strcpy(priv_fw->fw_version, (char *) (((unsigned long) msvdx_fw) + 
 
162
                        ((unsigned long) fw->fw_version)));
 
163
        } else if (!priv_fw) {
 
164
                printk(KERN_INFO "Kernel firmware is not loaded");
 
165
 
 
166
                return 1;
 
167
        }
 
168
 
 
169
    priv = gpDrmDevice->dev_private;
 
170
    context = priv->context;    
 
171
    mmio = context->device_context.virt_mmadr;
 
172
 
 
173
        //init_msvdx_first_time = 1;
 
174
    /* Reset MSVDX engine */
 
175
    EMGD_WRITE32(0x00000100, mmio + PSB_MSVDX_CONTROL);
 
176
    reg_ready_psb(context, PSB_MSVDX_CONTROL, 0x00000100, 0);
 
177
 
 
178
    /*
 
179
    * Make sure the clock is on.
 
180
    *
 
181
    * Clock enable bits are 0 - 6, with each bit controlling one of the
 
182
    * clocks.  For this, make sure all the clocks are enabled.
 
183
    */
 
184
    EMGD_WRITE32(PSB_CLK_ENABLE_ALL, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
 
185
 
 
186
    /* Set default MMU PTD to the same value used by the SGX */
 
187
    ctrl = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE1);
 
188
 
 
189
    address = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE1);
 
190
    EMGD_WRITE32(address, mmio + PSB_MSVDX_MMU_DIR_LIST_BASE0);
 
191
    EMGD_WRITE32(address, mmio + PSB_MSVDX_MMU_DIR_LIST_BASE1);
 
192
    EMGD_WRITE32(address, mmio + PSB_MSVDX_MMU_DIR_LIST_BASE2);
 
193
    EMGD_WRITE32(address, mmio + PSB_MSVDX_MMU_DIR_LIST_BASE3);
 
194
 
 
195
 
 
196
    /*
 
197
    * MMU Page size = 12
 
198
    * MMU best count = 7
 
199
    * MMU ADT TTE = 0
 
200
    * MMU TTE threshold = 12
 
201
    */
 
202
    EMGD_WRITE32(0xc070000c, mmio + PSB_MSVDX_MMU_CONTROL1);
 
203
 
 
204
 
 
205
    /* Flush the directory cache */
 
206
    ctrl = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0) | 0x0C; /* Flush */
 
207
    EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MMU_CONTROL0);
 
208
 
 
209
    /* Enable MMU by removing all bypass bits */
 
210
    EMGD_WRITE32(0, mmio + PSB_MSVDX_MMU_CONTROL0);
 
211
 
 
212
 
 
213
    /* Set up the RENDEC.
 
214
    *   The RENDEC requires two blocks of virtual address space so those
 
215
    *   must be allocated and then the RENDEC is initialized using those
 
216
    *   address ranges.
 
217
    *
 
218
    *   RENDEC control0:
 
219
    *     bit 3     1 - search MTX_to_MTX header
 
220
    *     bit 2     1 - skip next slice
 
221
    *     bit 1     1 - flush remaining bit stream
 
222
    *     bit 0     1 - initialize RENDEC
 
223
    *
 
224
    *   RENDEC control1:
 
225
    *     bit 24:   1 - enables data to be transferred through ext. memory
 
226
    *     bit 19:18 WR burst size (0 = 32 bytes, 1 = 64 bytes, 2 = 128 bytes)
 
227
    *     bit 17:16 RD burst size (0 = 32 bytes, 1 = 64 bytes, 2 = 128 bytes)
 
228
    *     bit  7: 0 start size (zero)
 
229
    */
 
230
 
 
231
    size0 = RENDEC_A_SIZE;
 
232
    size1 = RENDEC_B_SIZE;
 
233
 
 
234
    /*
 
235
    * These allocations need to be undone when shutting down.  Where
 
236
    * should they be saved?
 
237
    */
 
238
    if (init_msvdx_first_time) {
 
239
                base_addr0 = base0;
 
240
                base_addr1 = base1;
 
241
 
 
242
                //printk(KERN_INFO "get the base_addr=%lx, base_addr1=%lx\n", base_addr0,base_addr1);
 
243
 
 
244
        /* Save the offsets so it can be freed and restored later */
 
245
        platform = (platform_context_plb_t *)context->platform_context;
 
246
        platform->rendec_base0 = base_addr0;
 
247
        platform->rendec_base1 = base_addr1;
 
248
 
 
249
                init_msvdx_first_time = 0;
 
250
        INIT_LIST_HEAD(&platform->msvdx_queue);
 
251
                spin_lock_init(&platform->msvdx_lock);
 
252
    } else {
 
253
        /* restore offsets. */
 
254
        platform = (platform_context_plb_t *)context->platform_context;
 
255
        base_addr0 = platform->rendec_base0;
 
256
        base_addr1 = platform->rendec_base1;
 
257
 
 
258
        /* Init link list to fix HSD202831 */
 
259
        if(!context_count) {
 
260
                        INIT_LIST_HEAD(&platform->msvdx_queue);
 
261
                }
 
262
    }
 
263
 
 
264
        platform->msvdx_busy = 0;
 
265
    EMGD_WRITE32(base_addr0, mmio + PSB_MSVDX_RENDEC_BASE_ADDR0);
 
266
    EMGD_WRITE32(base_addr1, mmio + PSB_MSVDX_RENDEC_BASE_ADDR1);
 
267
 
 
268
    EMGD_WRITE32((((size1 / 4096) << 16) | (size0 / 4096)),
 
269
            mmio + PSB_MSVDX_RENDEC_BUFFER_SIZE);
 
270
 
 
271
    /* Rendec setup:
 
272
    *   Start size = 0
 
273
    *   Burst size R = 4 words
 
274
    *   Burst size W = 4 words
 
275
    *   External memory enabled
 
276
    *   Stream End = 0
 
277
    *   Slice mode = 0
 
278
    *   DEC disable = 0
 
279
    */
 
280
    EMGD_WRITE32(0x01050000, mmio + PSB_MSVDX_RENDEC_CONTROL1);
 
281
 
 
282
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT0);
 
283
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT1);
 
284
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT2);
 
285
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT3);
 
286
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT4);
 
287
    EMGD_WRITE32(0x00101010, mmio + PSB_MSVDX_RENDEC_CONTEXT5);
 
288
 
 
289
    EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_RENDEC_CONTROL0);
 
290
 
 
291
 
 
292
    /* Start Firmware Load process */
 
293
 
 
294
    /* Reset the MTX */
 
295
    EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MTX_SOFT_RESET);
 
296
 
 
297
        /* Reset the counter that looks for MSVDX getting into a bad state */
 
298
        jiffies_at_last_dequeue = 0;
 
299
 
 
300
    /*
 
301
    * Should this check the core revision and only do this if it is
 
302
    * a specific version or range of versions?
 
303
    *
 
304
    * Stepping prior to D0, need to set COMMS_OFFSET_FLAGS to 0
 
305
    * Stepping D0 should set MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0 (0x222)
 
306
    * Stepping D1 should set MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1 (0x220)
 
307
    */
 
308
 
 
309
    /* If POULSBO_D1 or later use MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION */
 
310
    EMGD_WRITE32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT,
 
311
            mmio + PSB_MSVDX_COMMS_OFFSET_FLAGS);
 
312
    /* Else EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_OFFSET_FLAGS); */
 
313
 
 
314
    /* Initialize communication control */
 
315
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_MSG_COUNTER);
 
316
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_SIGNATURE);
 
317
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_HOST_RD_INDEX);
 
318
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_HOST_WRT_INDEX);
 
319
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_MTX_RD_INDEX);
 
320
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_TO_MTX_WRT_INDEX);
 
321
    EMGD_WRITE32(0x00, mmio + PSB_MSVDX_COMMS_FW_STATUS);
 
322
 
 
323
    /*
 
324
    * Get the ram bank size
 
325
    *   The banks size seems to be a 4 bit value in the MTX debug register.
 
326
    *   Where this is documented other than the UMG code is not clear.
 
327
    */
 
328
    ram_bank = EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_BANK);
 
329
    bank_size = (ram_bank & 0x000f0000) >> 16;
 
330
    bank_size = (1 << (bank_size + 2));
 
331
 
 
332
    /* Firmware version? */
 
333
    printk(KERN_INFO "Firmware version is %s\n", priv_fw->fw_version);
 
334
 
 
335
    /* Save RAM access control register */
 
336
    acc_control = EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
 
337
 
 
338
    /* Loop writing text/code to core memory */
 
339
    current_bank = ~0L;
 
340
    address = PC_START_ADDRESS - MTX_CODE_BASE;
 
341
 
 
342
        fw_data = priv_fw->fw_text;
 
343
        fw_size = priv_fw->fw_text_size;
 
344
 
 
345
    for (i = 0; i < fw_size; i++) {
 
346
        /* Wait for MCMSTAT to become be idle 1 */
 
347
        if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
348
                    0xffffffff, 0x00000001) == 0) {
 
349
            ram_id = MTX_CORE_CODE_MEM + (address / bank_size);
 
350
            if (ram_id != current_bank) {
 
351
                /*
 
352
                * bits 20:27    - ram bank (CODE_BASE | DATA_BASE)
 
353
                * bits  2:19    - address
 
354
                * bit   1       - enable auto increment addressing mode
 
355
                */
 
356
                ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) |
 
357
                    0x02;
 
358
                EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
 
359
 
 
360
                current_bank = ram_id;
 
361
                /* Wait for MCMSTAT to become be idle 1 */
 
362
                reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
363
                        0xffffffff, 0x00000001);
 
364
            }
 
365
 
 
366
            address +=  4;
 
367
            EMGD_WRITE32(fw_data[i],
 
368
                    mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
 
369
        } else {
 
370
            printk(KERN_ERR "Timeout waiting for MCMSTAT to be idle\n");
 
371
        }
 
372
    }
 
373
 
 
374
    /* verify firmware upload. */
 
375
    current_bank = ~0L;
 
376
    address = PC_START_ADDRESS - MTX_CODE_BASE;
 
377
 
 
378
    for (i = 0; i < fw_size; i++) {
 
379
        if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
380
                    0xffffffff, 0x00000001) == 0) {
 
381
            ram_id = MTX_CORE_CODE_MEM + (address / bank_size);
 
382
            if (ram_id != current_bank) {
 
383
                /*
 
384
                * bits 20:27    - ram bank (CODE_BASE | DATA_BASE)
 
385
                * bits  2:19    - address
 
386
                * bit   1       - enable auto increment addressing mode
 
387
                */
 
388
                ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) |
 
389
                    0x03;
 
390
                EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
 
391
                current_bank = ram_id;
 
392
                reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
393
                        0xffffffff, 0x00000001);
 
394
            }
 
395
 
 
396
            address +=  4;
 
397
            if (EMGD_READ32(mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER) !=
 
398
                    fw_data[i]) {
 
399
                printk(KERN_ERR "Verify Error at index %ld\n", i);
 
400
            }
 
401
        } else {
 
402
            printk(KERN_ERR "Timeout waiting for MCMSTAT to be idle while verifying\n");
 
403
        }
 
404
    }
 
405
 
 
406
        fw_data = priv_fw->fw_data;
 
407
        fw_size = priv_fw->fw_data_size;
 
408
 
 
409
    /* Loop writing data to core memory */
 
410
    current_bank = ~0L;
 
411
    address = priv_fw->fw_data_location - MTX_DATA_BASE;
 
412
 
 
413
    for (i = 0; i < fw_size; i++) {
 
414
        if (reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
415
                    0xffffffff, 0x00000001) == 0) {
 
416
            ram_id = MTX_CORE_DATA_MEM + (address / bank_size);
 
417
            if (ram_id != current_bank) {
 
418
                /*
 
419
                * bits 20:27    - ram bank (CODE_BASE | DATA_BASE)
 
420
                * bits  2:19    - address
 
421
                * bit   1       - enable auto increment addressing mode
 
422
                */
 
423
                ctrl = (ram_id << 20) | (((address >> 2) & 0x000ffffc) << 2) |
 
424
                    0x02;
 
425
                EMGD_WRITE32(ctrl, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
 
426
                current_bank = ram_id;
 
427
                reg_ready_psb(context, PSB_MSVDX_MTX_RAM_ACCESS_STATUS,
 
428
                        0xffffffff, 0x00000001);
 
429
            }
 
430
 
 
431
            address +=  4;
 
432
            EMGD_WRITE32(fw_data[i],
 
433
                    mmio + PSB_MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
 
434
        } else {
 
435
            printk(KERN_ERR "Timeout waiting for MCMSTAT to be idle - data segment\n");
 
436
        }
 
437
    }
 
438
 
 
439
    /* Restore the RAM access control register */
 
440
    EMGD_WRITE32(acc_control, mmio + PSB_MSVDX_MTX_RAM_ACCESS_CONTROL);
 
441
 
 
442
    /* Start the firmware thread running */
 
443
    EMGD_WRITE32(PC_START_ADDRESS, mmio + PSB_MSVDX_MTX_REGISTER_READ_WRITE_DATA);
 
444
    EMGD_WRITE32(MTX_PC, mmio + PSB_MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);
 
445
    reg_ready_psb(context, PSB_MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
 
446
            0x80000000, 0x80000000);
 
447
 
 
448
    /* Enable the MTX */
 
449
    printk(KERN_INFO "Enabling MTX 0x%x\n", EMGD_READ32(mmio + PSB_MSVDX_MTX_ENABLE));
 
450
    EMGD_WRITE32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, mmio + PSB_MSVDX_MTX_ENABLE);
 
451
    printk(KERN_INFO "Enabled MTX 0x%x\n", EMGD_READ32(mmio + PSB_MSVDX_MTX_ENABLE));
 
452
 
 
453
    /*
 
454
    * Wait for signature value to be written.
 
455
    *
 
456
    * This is how the firmware thread notifies us that it is running.
 
457
    */
 
458
    if (reg_ready_psb(context, PSB_MSVDX_COMMS_SIGNATURE, 0xffffffff,
 
459
                0xA5A5A5A5)){
 
460
        /* Error initializing firmware.... */
 
461
        EMGD_DEBUG("Error, no MSVDX COMMS Signature");
 
462
        return 0; /* FIXME: return an error code */
 
463
    }
 
464
    printk(KERN_INFO "MSVDX COMMS Signature OK\n");
 
465
 
 
466
    /* Locate message buffers */
 
467
    platform->mtx_buf_size = EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_MTX_BUF_SIZE) & 0xFFFF;
 
468
    platform->host_buf_size = EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_HOST_BUF_SIZE) & 0xFFFF;
 
469
    platform->mtx_buf_offset = MSVDX_BASE + (EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_MTX_BUF_SIZE) >> 16) + 0x2000;
 
470
    platform->host_buf_offset = MSVDX_BASE + (EMGD_READ32(mmio+PSB_MSVDX_COMMS_TO_HOST_BUF_SIZE) >> 16) + 0x2000;
 
471
 
 
472
    platform->sequence = 1;
 
473
    platform->mtx_submitted = 0;
 
474
 
 
475
    /* Send initialization message to firmware, newer versions don't */
 
476
    if (0) {
 
477
        unsigned long init_msg[2];
 
478
 
 
479
        init_msg[0] = 8 | (0x80 << 8);
 
480
 
 
481
        /* physical address of the PD shared by SGX/MSVDX */
 
482
        init_msg[1] = EMGD_READ32(mmio + 0x40c84);
 
483
 
 
484
        send_to_mtx(context, init_msg);
 
485
 
 
486
        /* Check response from MTX firmware */
 
487
        poll_mtx_irq(context);
 
488
    }
 
489
 
 
490
    /* Clear the firmware buffer, this is mostly to make debugging easier */
 
491
    if (1) {
 
492
        unsigned long i;
 
493
 
 
494
        for (i = 0; i < platform->mtx_buf_size; i++) {
 
495
            EMGD_WRITE32(0, mmio + platform->mtx_buf_offset + (i <<2));
 
496
        }
 
497
        for (i = 0; i < platform->host_buf_size; i++) {
 
498
            EMGD_WRITE32(0, mmio + platform->host_buf_offset + (i <<2));
 
499
        }
 
500
    }
 
501
 
 
502
 
 
503
    /* Enable minimal clocks */
 
504
    EMGD_WRITE32(PSB_CLK_ENABLE_MIN, mmio + PSB_MSVDX_MAN_CLK_ENABLE);
 
505
 
 
506
    /* Enable MTX interrupts to host */
 
507
    EMGD_WRITE32(1<<14, mmio + PSB_MSVDX_HOST_INTERRUPT_ENABLE);
 
508
 
 
509
 
 
510
    /* Are we done? */
 
511
    EMGD_TRACE_EXIT;
 
512
    return 0; /* Successfully initialized the MTX firmware */
 
513
}
 
514
 
 
515
 
 
516
int msvdx_uninit_plb(igd_context_t *context) 
 
517
 
518
        EMGD_TRACE_ENTER; 
 
519
 
 
520
        if(!context_count) { 
 
521
                msvdx_reset_plb(context); 
 
522
        }
 
523
        EMGD_TRACE_EXIT; 
 
524
        return 0; 
 
525
 
526
    
 
527
 
 
528
int msvdx_close_context(igd_context_t *context)
 
529
{
 
530
        EMGD_TRACE_ENTER;
 
531
 
 
532
        if(context_count) {
 
533
                context_count -= 1;
 
534
        } else {
 
535
                EMGD_TRACE_EXIT;
 
536
                return 1;
 
537
        }
 
538
 
 
539
        EMGD_TRACE_EXIT;
 
540
        return 0;
 
541
}
 
542
 
 
543
int msvdx_create_context(igd_context_t *context)
 
544
{
 
545
        EMGD_TRACE_ENTER;
 
546
 
 
547
        context_count +=1;
 
548
 
 
549
        EMGD_TRACE_EXIT;
 
550
        return 0;
 
551
}
 
552
 
 
553
int process_video_decode_plb(igd_context_t *context, unsigned long offset, void *virt_addr, unsigned long *fence_id)
 
554
{
 
555
        unsigned long *mtx_buf;
 
556
    unsigned long *mtx_msgs;
 
557
    unsigned long mtx_offset;
 
558
    unsigned long mtx_msg_cnt;
 
559
    unsigned long irq_flags;
 
560
        int ret = 0;
 
561
    platform_context_plb_t *platform;
 
562
 
 
563
    EMGD_TRACE_ENTER;
 
564
 
 
565
 
 
566
    platform = (platform_context_plb_t *)context->platform_context;
 
567
 
 
568
        mtx_buf = (unsigned long *) virt_addr;
 
569
    mtx_offset = mtx_buf[0];
 
570
    mtx_msg_cnt = mtx_buf[1];
 
571
 
 
572
//      printk(KERN_INFO "process_video_decode_plb where buf=%lx, offset=%lx, cnt=%lx\n",
 
573
//                              mtx_buf, offset, mtx_msg_cnt);
 
574
    if (mtx_msg_cnt > 0x20) {
 
575
        printk(KERN_ERR "Message count too big at %ld\n", mtx_msg_cnt);
 
576
        return -EINVAL;
 
577
    }
 
578
 
 
579
    mtx_msgs = mtx_buf + (mtx_offset / sizeof (unsigned long));
 
580
        if (mtx_msg_cnt > 0) {
 
581
        //if ((mtx_buf[0] != 0x8) || (mtx_buf[2] != 0x8504)) {
 
582
 
 
583
                spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
 
584
 
 
585
                if (!platform->msvdx_busy) {
 
586
 
 
587
                        platform->msvdx_busy = 1;
 
588
                        spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
 
589
 
 
590
 
 
591
                        if (platform->msvdx_needs_reset) {
 
592
                                msvdx_reset_plb(context);
 
593
                                msvdx_init_plb(0, 0, NULL, 0);
 
594
                                jiffies_at_last_dequeue = 0;
 
595
                        }
 
596
                        // Send message buffer to MSVDX Firmware
 
597
 
 
598
                        populate_fence_id(context, mtx_msgs, mtx_msg_cnt);
 
599
                        ret = process_mtx_messages(context, mtx_msgs, mtx_msg_cnt, platform->msvdx_fence);
 
600
 
 
601
                        if (ret) {
 
602
                                ret = -EINVAL;
 
603
 
 
604
                        }
 
605
                } else {
 
606
                        struct msvdx_cmd_queue *msvdx_cmd;
 
607
 
 
608
                        spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
 
609
 
 
610
                        msvdx_cmd = kzalloc(sizeof(struct msvdx_cmd_queue), GFP_KERNEL);
 
611
                        if (msvdx_cmd == NULL) {
 
612
                                printk(KERN_ERR "MSVDXQUE: Out of memory\n");
 
613
                                return -ENOMEM;
 
614
                        }
 
615
 
 
616
                        populate_fence_id(context, mtx_msgs, mtx_msg_cnt);
 
617
                        msvdx_cmd->cmd = mtx_msgs;
 
618
                        msvdx_cmd->cmd_size = mtx_msg_cnt;
 
619
                        /* If more than 1000 msec (1 second or 1000 jiffies) passes since
 
620
                         * the last time a video cmd has been decoded, MSVDX may be hung
 
621
                         * and needing to be reset.
 
622
                         */
 
623
                        if ((jiffies_at_last_dequeue != 0) &&
 
624
                                ((jiffies - jiffies_at_last_dequeue) > 1000)) {
 
625
                                printk(KERN_ERR "Video decode hardware appears to be hung; "
 
626
                                        "resetting\n");
 
627
                                platform->msvdx_needs_reset = 1;
 
628
                        }
 
629
                        if (platform->msvdx_needs_reset) {
 
630
                                msvdx_reset_plb(context);
 
631
                                msvdx_init_plb(0, 0, NULL, 0);
 
632
                                platform->msvdx_busy = 0;
 
633
                                jiffies_at_last_dequeue = 0;
 
634
                        }
 
635
 
 
636
                        spin_lock_irqsave(&platform->msvdx_lock, irq_flags);
 
637
                        list_add_tail(&msvdx_cmd->head, &platform->msvdx_queue);
 
638
                        if (!platform->msvdx_busy) {
 
639
                                platform->msvdx_busy = 1;
 
640
                                msvdx_dequeue_send(context);
 
641
                        }
 
642
 
 
643
                        spin_unlock_irqrestore(&platform->msvdx_lock, irq_flags);
 
644
 
 
645
                }
 
646
                *fence_id = platform->msvdx_fence;
 
647
        } else {
 
648
                /* return the fence id even there is no messages to process.
 
649
                 * Used this for context id.
 
650
                 */
 
651
                *fence_id = platform->msvdx_fence;
 
652
        }
 
653
 
 
654
        return ret;
 
655
}
 
656
 
 
657
int msvdx_get_fence_id(igd_context_t *context, unsigned long *fence_id)
 
658
{
 
659
        int ret = 0;
 
660
    platform_context_plb_t *platform;
 
661
 
 
662
    platform = (platform_context_plb_t *)context->platform_context;
 
663
 
 
664
        *fence_id = platform->mtx_completed;
 
665
 
 
666
        return ret;
 
667
}
 
668
 
 
669
int msvdx_flush_tlb(igd_context_t *context)
 
670
{
 
671
        unsigned char *mmio = context->device_context.virt_mmadr;
 
672
        unsigned long msvdx_mmu;
 
673
        msvdx_mmu = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
 
674
        msvdx_mmu &= 0xFFFFFFF0;
 
675
        msvdx_mmu |= 0x0C;      /* MMU_INVALDC + MMU_FLUSH */
 
676
        EMGD_WRITE32(msvdx_mmu, mmio + PSB_MSVDX_MMU_CONTROL0);
 
677
 
 
678
        msvdx_mmu = EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
 
679
        msvdx_mmu &= 0xFFFFFF00;
 
680
        EMGD_WRITE32(msvdx_mmu, mmio + PSB_MSVDX_MMU_CONTROL0);
 
681
        EMGD_READ32(mmio + PSB_MSVDX_MMU_CONTROL0);
 
682
 
 
683
        return 0;
 
684
 
 
685
}
 
686
 
 
687
 
 
688
/*
 
689
 * Resets the MSVDX engine via the soft reset control.
 
690
 *
 
691
 * This function is exported.
 
692
 */
 
693
void msvdx_reset_plb(igd_context_t *context)
 
694
{
 
695
    unsigned char *mmio = context->device_context.virt_mmadr;
 
696
    platform_context_plb_t *platform;
 
697
 
 
698
    EMGD_TRACE_ENTER;
 
699
 
 
700
    platform = (platform_context_plb_t *)context->platform_context;
 
701
 
 
702
    /* Reset MSVDX engine */
 
703
    EMGD_WRITE32(0x11111100, mmio + PSB_MSVDX_CONTROL);
 
704
    reg_ready_psb(context, PSB_MSVDX_CONTROL, 0x00000100, 0);
 
705
 
 
706
    /* Clear interrupt and clear pending interrupts */
 
707
    EMGD_WRITE32(0, mmio + PSB_MSVDX_HOST_INTERRUPT_ENABLE);
 
708
    EMGD_WRITE32(0xffffffff, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
 
709
 
 
710
    /* Mark the engine as being reset */
 
711
    platform->msvdx_needs_reset = 0;
 
712
}
 
713
 
 
714
 
 
715
/*
 
716
 * When shuting down, need to reset the MSVDX engine too.
 
717
 */
 
718
int msvdx_shutdown_plb(igd_context_t *context)
 
719
{
 
720
        platform_context_plb_t *platform;
 
721
 
 
722
        EMGD_TRACE_ENTER;
 
723
        platform = (platform_context_plb_t *)context->platform_context;
 
724
 
 
725
        /* Reset MSVDX engine */
 
726
        msvdx_reset_plb(context);
 
727
 
 
728
        /* Free RENDEC memory allocations */
 
729
        platform->rendec_base0 = 0;
 
730
        platform->rendec_base1 = 0;
 
731
        init_msvdx_first_time = 1;
 
732
 
 
733
        EMGD_TRACE_EXIT;
 
734
        return 0;
 
735
}
 
736
 
 
737
static int reg_ready_psb(igd_context_t *context,
 
738
        unsigned long reg,
 
739
        unsigned long mask,
 
740
        unsigned long value)
 
741
{
 
742
    unsigned char *mmio = context->device_context.virt_mmadr;
 
743
    unsigned long status;
 
744
    int poll_cnt = 1000;
 
745
 
 
746
    while (poll_cnt) {
 
747
        status = EMGD_READ32(mmio + reg);
 
748
        if ((status & mask) == value) {
 
749
            return 0;
 
750
        }
 
751
        poll_cnt--;
 
752
        OS_SLEEP(100);
 
753
    }
 
754
 
 
755
    /* Timeout waiting for RAM ACCESS ready */
 
756
    EMGD_DEBUG("TIMEOUT: Got 0x%08lx while waiting for 0x%08lx", status, value);
 
757
    return 1;
 
758
}
 
759
 
 
760
 
 
761
static int poll_mtx_irq(igd_context_t *context)
 
762
{
 
763
    unsigned char *mmio = context->device_context.virt_mmadr;
 
764
    int ret;
 
765
    unsigned long mtx_int;
 
766
 
 
767
    EMGD_TRACE_ENTER;
 
768
    mtx_int = (1 << 14);
 
769
 
 
770
    ret = reg_ready_psb(context, PSB_MSVDX_INTERRUPT_STATUS, mtx_int, mtx_int);
 
771
    if (ret) {
 
772
        /* Timeout waiting on interrupt status */
 
773
        return ret;
 
774
    }
 
775
 
 
776
    /* Clear the interrupt */
 
777
    EMGD_WRITE32(mtx_int, mmio + PSB_MSVDX_INTERRUPT_CLEAR);
 
778
 
 
779
    return ret;
 
780
}
 
781