~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to drivers/gpu/drm/radeon/evergreen_cs.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2010 Advanced Micro Devices, Inc.
 
3
 * Copyright 2008 Red Hat Inc.
 
4
 * Copyright 2009 Jerome Glisse.
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the "Software"),
 
8
 * to deal in the Software without restriction, including without limitation
 
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
10
 * and/or sell copies of the Software, and to permit persons to whom the
 
11
 * Software is furnished to do so, subject to the following conditions:
 
12
 *
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 *
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
19
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
22
 * OTHER DEALINGS IN THE SOFTWARE.
 
23
 *
 
24
 * Authors: Dave Airlie
 
25
 *          Alex Deucher
 
26
 *          Jerome Glisse
 
27
 */
 
28
#include "drmP.h"
 
29
#include "radeon.h"
 
30
#include "evergreend.h"
 
31
#include "evergreen_reg_safe.h"
 
32
 
 
33
static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
 
34
                                          struct radeon_cs_reloc **cs_reloc);
 
35
 
 
36
struct evergreen_cs_track {
 
37
        u32                     group_size;
 
38
        u32                     nbanks;
 
39
        u32                     npipes;
 
40
        /* value we track */
 
41
        u32                     nsamples;
 
42
        u32                     cb_color_base_last[12];
 
43
        struct radeon_bo        *cb_color_bo[12];
 
44
        u32                     cb_color_bo_offset[12];
 
45
        struct radeon_bo        *cb_color_fmask_bo[8];
 
46
        struct radeon_bo        *cb_color_cmask_bo[8];
 
47
        u32                     cb_color_info[12];
 
48
        u32                     cb_color_view[12];
 
49
        u32                     cb_color_pitch_idx[12];
 
50
        u32                     cb_color_slice_idx[12];
 
51
        u32                     cb_color_dim_idx[12];
 
52
        u32                     cb_color_dim[12];
 
53
        u32                     cb_color_pitch[12];
 
54
        u32                     cb_color_slice[12];
 
55
        u32                     cb_color_cmask_slice[8];
 
56
        u32                     cb_color_fmask_slice[8];
 
57
        u32                     cb_target_mask;
 
58
        u32                     cb_shader_mask;
 
59
        u32                     vgt_strmout_config;
 
60
        u32                     vgt_strmout_buffer_config;
 
61
        u32                     db_depth_control;
 
62
        u32                     db_depth_view;
 
63
        u32                     db_depth_size;
 
64
        u32                     db_depth_size_idx;
 
65
        u32                     db_z_info;
 
66
        u32                     db_z_idx;
 
67
        u32                     db_z_read_offset;
 
68
        u32                     db_z_write_offset;
 
69
        struct radeon_bo        *db_z_read_bo;
 
70
        struct radeon_bo        *db_z_write_bo;
 
71
        u32                     db_s_info;
 
72
        u32                     db_s_idx;
 
73
        u32                     db_s_read_offset;
 
74
        u32                     db_s_write_offset;
 
75
        struct radeon_bo        *db_s_read_bo;
 
76
        struct radeon_bo        *db_s_write_bo;
 
77
};
 
78
 
 
79
static void evergreen_cs_track_init(struct evergreen_cs_track *track)
 
80
{
 
81
        int i;
 
82
 
 
83
        for (i = 0; i < 8; i++) {
 
84
                track->cb_color_fmask_bo[i] = NULL;
 
85
                track->cb_color_cmask_bo[i] = NULL;
 
86
                track->cb_color_cmask_slice[i] = 0;
 
87
                track->cb_color_fmask_slice[i] = 0;
 
88
        }
 
89
 
 
90
        for (i = 0; i < 12; i++) {
 
91
                track->cb_color_base_last[i] = 0;
 
92
                track->cb_color_bo[i] = NULL;
 
93
                track->cb_color_bo_offset[i] = 0xFFFFFFFF;
 
94
                track->cb_color_info[i] = 0;
 
95
                track->cb_color_view[i] = 0;
 
96
                track->cb_color_pitch_idx[i] = 0;
 
97
                track->cb_color_slice_idx[i] = 0;
 
98
                track->cb_color_dim[i] = 0;
 
99
                track->cb_color_pitch[i] = 0;
 
100
                track->cb_color_slice[i] = 0;
 
101
                track->cb_color_dim[i] = 0;
 
102
        }
 
103
        track->cb_target_mask = 0xFFFFFFFF;
 
104
        track->cb_shader_mask = 0xFFFFFFFF;
 
105
 
 
106
        track->db_depth_view = 0xFFFFC000;
 
107
        track->db_depth_size = 0xFFFFFFFF;
 
108
        track->db_depth_size_idx = 0;
 
109
        track->db_depth_control = 0xFFFFFFFF;
 
110
        track->db_z_info = 0xFFFFFFFF;
 
111
        track->db_z_idx = 0xFFFFFFFF;
 
112
        track->db_z_read_offset = 0xFFFFFFFF;
 
113
        track->db_z_write_offset = 0xFFFFFFFF;
 
114
        track->db_z_read_bo = NULL;
 
115
        track->db_z_write_bo = NULL;
 
116
        track->db_s_info = 0xFFFFFFFF;
 
117
        track->db_s_idx = 0xFFFFFFFF;
 
118
        track->db_s_read_offset = 0xFFFFFFFF;
 
119
        track->db_s_write_offset = 0xFFFFFFFF;
 
120
        track->db_s_read_bo = NULL;
 
121
        track->db_s_write_bo = NULL;
 
122
}
 
123
 
 
124
static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 
125
{
 
126
        /* XXX fill in */
 
127
        return 0;
 
128
}
 
129
 
 
130
static int evergreen_cs_track_check(struct radeon_cs_parser *p)
 
131
{
 
132
        struct evergreen_cs_track *track = p->track;
 
133
 
 
134
        /* we don't support stream out buffer yet */
 
135
        if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
 
136
                dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
 
137
                return -EINVAL;
 
138
        }
 
139
 
 
140
        /* XXX fill in */
 
141
        return 0;
 
142
}
 
143
 
 
144
/**
 
145
 * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
 
146
 * @parser:     parser structure holding parsing context.
 
147
 * @pkt:        where to store packet informations
 
148
 *
 
149
 * Assume that chunk_ib_index is properly set. Will return -EINVAL
 
150
 * if packet is bigger than remaining ib size. or if packets is unknown.
 
151
 **/
 
152
int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
 
153
                              struct radeon_cs_packet *pkt,
 
154
                              unsigned idx)
 
155
{
 
156
        struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
 
157
        uint32_t header;
 
158
 
 
159
        if (idx >= ib_chunk->length_dw) {
 
160
                DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
 
161
                          idx, ib_chunk->length_dw);
 
162
                return -EINVAL;
 
163
        }
 
164
        header = radeon_get_ib_value(p, idx);
 
165
        pkt->idx = idx;
 
166
        pkt->type = CP_PACKET_GET_TYPE(header);
 
167
        pkt->count = CP_PACKET_GET_COUNT(header);
 
168
        pkt->one_reg_wr = 0;
 
169
        switch (pkt->type) {
 
170
        case PACKET_TYPE0:
 
171
                pkt->reg = CP_PACKET0_GET_REG(header);
 
172
                break;
 
173
        case PACKET_TYPE3:
 
174
                pkt->opcode = CP_PACKET3_GET_OPCODE(header);
 
175
                break;
 
176
        case PACKET_TYPE2:
 
177
                pkt->count = -1;
 
178
                break;
 
179
        default:
 
180
                DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
 
181
                return -EINVAL;
 
182
        }
 
183
        if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
 
184
                DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
 
185
                          pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
 
186
                return -EINVAL;
 
187
        }
 
188
        return 0;
 
189
}
 
190
 
 
191
/**
 
192
 * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
 
193
 * @parser:             parser structure holding parsing context.
 
194
 * @data:               pointer to relocation data
 
195
 * @offset_start:       starting offset
 
196
 * @offset_mask:        offset mask (to align start offset on)
 
197
 * @reloc:              reloc informations
 
198
 *
 
199
 * Check next packet is relocation packet3, do bo validation and compute
 
200
 * GPU offset using the provided start.
 
201
 **/
 
202
static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
 
203
                                          struct radeon_cs_reloc **cs_reloc)
 
204
{
 
205
        struct radeon_cs_chunk *relocs_chunk;
 
206
        struct radeon_cs_packet p3reloc;
 
207
        unsigned idx;
 
208
        int r;
 
209
 
 
210
        if (p->chunk_relocs_idx == -1) {
 
211
                DRM_ERROR("No relocation chunk !\n");
 
212
                return -EINVAL;
 
213
        }
 
214
        *cs_reloc = NULL;
 
215
        relocs_chunk = &p->chunks[p->chunk_relocs_idx];
 
216
        r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
 
217
        if (r) {
 
218
                return r;
 
219
        }
 
220
        p->idx += p3reloc.count + 2;
 
221
        if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
 
222
                DRM_ERROR("No packet3 for relocation for packet at %d.\n",
 
223
                          p3reloc.idx);
 
224
                return -EINVAL;
 
225
        }
 
226
        idx = radeon_get_ib_value(p, p3reloc.idx + 1);
 
227
        if (idx >= relocs_chunk->length_dw) {
 
228
                DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
 
229
                          idx, relocs_chunk->length_dw);
 
230
                return -EINVAL;
 
231
        }
 
232
        /* FIXME: we assume reloc size is 4 dwords */
 
233
        *cs_reloc = p->relocs_ptr[(idx / 4)];
 
234
        return 0;
 
235
}
 
236
 
 
237
/**
 
238
 * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
 
239
 * @parser:             parser structure holding parsing context.
 
240
 *
 
241
 * Check next packet is relocation packet3, do bo validation and compute
 
242
 * GPU offset using the provided start.
 
243
 **/
 
244
static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
 
245
{
 
246
        struct radeon_cs_packet p3reloc;
 
247
        int r;
 
248
 
 
249
        r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
 
250
        if (r) {
 
251
                return 0;
 
252
        }
 
253
        if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
 
254
                return 0;
 
255
        }
 
256
        return 1;
 
257
}
 
258
 
 
259
/**
 
260
 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
 
261
 * @parser:             parser structure holding parsing context.
 
262
 *
 
263
 * Userspace sends a special sequence for VLINE waits.
 
264
 * PACKET0 - VLINE_START_END + value
 
265
 * PACKET3 - WAIT_REG_MEM poll vline status reg
 
266
 * RELOC (P3) - crtc_id in reloc.
 
267
 *
 
268
 * This function parses this and relocates the VLINE START END
 
269
 * and WAIT_REG_MEM packets to the correct crtc.
 
270
 * It also detects a switched off crtc and nulls out the
 
271
 * wait in that case.
 
272
 */
 
273
static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
 
274
{
 
275
        struct drm_mode_object *obj;
 
276
        struct drm_crtc *crtc;
 
277
        struct radeon_crtc *radeon_crtc;
 
278
        struct radeon_cs_packet p3reloc, wait_reg_mem;
 
279
        int crtc_id;
 
280
        int r;
 
281
        uint32_t header, h_idx, reg, wait_reg_mem_info;
 
282
        volatile uint32_t *ib;
 
283
 
 
284
        ib = p->ib->ptr;
 
285
 
 
286
        /* parse the WAIT_REG_MEM */
 
287
        r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
 
288
        if (r)
 
289
                return r;
 
290
 
 
291
        /* check its a WAIT_REG_MEM */
 
292
        if (wait_reg_mem.type != PACKET_TYPE3 ||
 
293
            wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
 
294
                DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
 
295
                r = -EINVAL;
 
296
                return r;
 
297
        }
 
298
 
 
299
        wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
 
300
        /* bit 4 is reg (0) or mem (1) */
 
301
        if (wait_reg_mem_info & 0x10) {
 
302
                DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
 
303
                r = -EINVAL;
 
304
                return r;
 
305
        }
 
306
        /* waiting for value to be equal */
 
307
        if ((wait_reg_mem_info & 0x7) != 0x3) {
 
308
                DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
 
309
                r = -EINVAL;
 
310
                return r;
 
311
        }
 
312
        if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
 
313
                DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
 
314
                r = -EINVAL;
 
315
                return r;
 
316
        }
 
317
 
 
318
        if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
 
319
                DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
 
320
                r = -EINVAL;
 
321
                return r;
 
322
        }
 
323
 
 
324
        /* jump over the NOP */
 
325
        r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
 
326
        if (r)
 
327
                return r;
 
328
 
 
329
        h_idx = p->idx - 2;
 
330
        p->idx += wait_reg_mem.count + 2;
 
331
        p->idx += p3reloc.count + 2;
 
332
 
 
333
        header = radeon_get_ib_value(p, h_idx);
 
334
        crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
 
335
        reg = CP_PACKET0_GET_REG(header);
 
336
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
 
337
        if (!obj) {
 
338
                DRM_ERROR("cannot find crtc %d\n", crtc_id);
 
339
                r = -EINVAL;
 
340
                goto out;
 
341
        }
 
342
        crtc = obj_to_crtc(obj);
 
343
        radeon_crtc = to_radeon_crtc(crtc);
 
344
        crtc_id = radeon_crtc->crtc_id;
 
345
 
 
346
        if (!crtc->enabled) {
 
347
                /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
 
348
                ib[h_idx + 2] = PACKET2(0);
 
349
                ib[h_idx + 3] = PACKET2(0);
 
350
                ib[h_idx + 4] = PACKET2(0);
 
351
                ib[h_idx + 5] = PACKET2(0);
 
352
                ib[h_idx + 6] = PACKET2(0);
 
353
                ib[h_idx + 7] = PACKET2(0);
 
354
                ib[h_idx + 8] = PACKET2(0);
 
355
        } else {
 
356
                switch (reg) {
 
357
                case EVERGREEN_VLINE_START_END:
 
358
                        header &= ~R600_CP_PACKET0_REG_MASK;
 
359
                        header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
 
360
                        ib[h_idx] = header;
 
361
                        ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
 
362
                        break;
 
363
                default:
 
364
                        DRM_ERROR("unknown crtc reloc\n");
 
365
                        r = -EINVAL;
 
366
                        goto out;
 
367
                }
 
368
        }
 
369
out:
 
370
        return r;
 
371
}
 
372
 
 
373
static int evergreen_packet0_check(struct radeon_cs_parser *p,
 
374
                                   struct radeon_cs_packet *pkt,
 
375
                                   unsigned idx, unsigned reg)
 
376
{
 
377
        int r;
 
378
 
 
379
        switch (reg) {
 
380
        case EVERGREEN_VLINE_START_END:
 
381
                r = evergreen_cs_packet_parse_vline(p);
 
382
                if (r) {
 
383
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
 
384
                                        idx, reg);
 
385
                        return r;
 
386
                }
 
387
                break;
 
388
        default:
 
389
                printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
 
390
                       reg, idx);
 
391
                return -EINVAL;
 
392
        }
 
393
        return 0;
 
394
}
 
395
 
 
396
static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
 
397
                                      struct radeon_cs_packet *pkt)
 
398
{
 
399
        unsigned reg, i;
 
400
        unsigned idx;
 
401
        int r;
 
402
 
 
403
        idx = pkt->idx + 1;
 
404
        reg = pkt->reg;
 
405
        for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
 
406
                r = evergreen_packet0_check(p, pkt, idx, reg);
 
407
                if (r) {
 
408
                        return r;
 
409
                }
 
410
        }
 
411
        return 0;
 
412
}
 
413
 
 
414
/**
 
415
 * evergreen_cs_check_reg() - check if register is authorized or not
 
416
 * @parser: parser structure holding parsing context
 
417
 * @reg: register we are testing
 
418
 * @idx: index into the cs buffer
 
419
 *
 
420
 * This function will test against evergreen_reg_safe_bm and return 0
 
421
 * if register is safe. If register is not flag as safe this function
 
422
 * will test it against a list of register needind special handling.
 
423
 */
 
424
static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
 
425
{
 
426
        struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
 
427
        struct radeon_cs_reloc *reloc;
 
428
        u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
 
429
        u32 m, i, tmp, *ib;
 
430
        int r;
 
431
 
 
432
        i = (reg >> 7);
 
433
        if (i > last_reg) {
 
434
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 
435
                return -EINVAL;
 
436
        }
 
437
        m = 1 << ((reg >> 2) & 31);
 
438
        if (!(evergreen_reg_safe_bm[i] & m))
 
439
                return 0;
 
440
        ib = p->ib->ptr;
 
441
        switch (reg) {
 
442
        /* force following reg to 0 in an attemp to disable out buffer
 
443
         * which will need us to better understand how it works to perform
 
444
         * security check on it (Jerome)
 
445
         */
 
446
        case SQ_ESGS_RING_SIZE:
 
447
        case SQ_GSVS_RING_SIZE:
 
448
        case SQ_ESTMP_RING_SIZE:
 
449
        case SQ_GSTMP_RING_SIZE:
 
450
        case SQ_HSTMP_RING_SIZE:
 
451
        case SQ_LSTMP_RING_SIZE:
 
452
        case SQ_PSTMP_RING_SIZE:
 
453
        case SQ_VSTMP_RING_SIZE:
 
454
        case SQ_ESGS_RING_ITEMSIZE:
 
455
        case SQ_ESTMP_RING_ITEMSIZE:
 
456
        case SQ_GSTMP_RING_ITEMSIZE:
 
457
        case SQ_GSVS_RING_ITEMSIZE:
 
458
        case SQ_GS_VERT_ITEMSIZE:
 
459
        case SQ_GS_VERT_ITEMSIZE_1:
 
460
        case SQ_GS_VERT_ITEMSIZE_2:
 
461
        case SQ_GS_VERT_ITEMSIZE_3:
 
462
        case SQ_GSVS_RING_OFFSET_1:
 
463
        case SQ_GSVS_RING_OFFSET_2:
 
464
        case SQ_GSVS_RING_OFFSET_3:
 
465
        case SQ_HSTMP_RING_ITEMSIZE:
 
466
        case SQ_LSTMP_RING_ITEMSIZE:
 
467
        case SQ_PSTMP_RING_ITEMSIZE:
 
468
        case SQ_VSTMP_RING_ITEMSIZE:
 
469
        case VGT_TF_RING_SIZE:
 
470
                /* get value to populate the IB don't remove */
 
471
                tmp =radeon_get_ib_value(p, idx);
 
472
                ib[idx] = 0;
 
473
                break;
 
474
        case DB_DEPTH_CONTROL:
 
475
                track->db_depth_control = radeon_get_ib_value(p, idx);
 
476
                break;
 
477
        case DB_Z_INFO:
 
478
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
479
                if (r) {
 
480
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
481
                                        "0x%04X\n", reg);
 
482
                        return -EINVAL;
 
483
                }
 
484
                track->db_z_info = radeon_get_ib_value(p, idx);
 
485
                ib[idx] &= ~Z_ARRAY_MODE(0xf);
 
486
                track->db_z_info &= ~Z_ARRAY_MODE(0xf);
 
487
                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
 
488
                        ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
489
                        track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
490
                } else {
 
491
                        ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
492
                        track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
493
                }
 
494
                break;
 
495
        case DB_STENCIL_INFO:
 
496
                track->db_s_info = radeon_get_ib_value(p, idx);
 
497
                break;
 
498
        case DB_DEPTH_VIEW:
 
499
                track->db_depth_view = radeon_get_ib_value(p, idx);
 
500
                break;
 
501
        case DB_DEPTH_SIZE:
 
502
                track->db_depth_size = radeon_get_ib_value(p, idx);
 
503
                track->db_depth_size_idx = idx;
 
504
                break;
 
505
        case DB_Z_READ_BASE:
 
506
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
507
                if (r) {
 
508
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
509
                                        "0x%04X\n", reg);
 
510
                        return -EINVAL;
 
511
                }
 
512
                track->db_z_read_offset = radeon_get_ib_value(p, idx);
 
513
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
514
                track->db_z_read_bo = reloc->robj;
 
515
                break;
 
516
        case DB_Z_WRITE_BASE:
 
517
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
518
                if (r) {
 
519
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
520
                                        "0x%04X\n", reg);
 
521
                        return -EINVAL;
 
522
                }
 
523
                track->db_z_write_offset = radeon_get_ib_value(p, idx);
 
524
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
525
                track->db_z_write_bo = reloc->robj;
 
526
                break;
 
527
        case DB_STENCIL_READ_BASE:
 
528
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
529
                if (r) {
 
530
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
531
                                        "0x%04X\n", reg);
 
532
                        return -EINVAL;
 
533
                }
 
534
                track->db_s_read_offset = radeon_get_ib_value(p, idx);
 
535
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
536
                track->db_s_read_bo = reloc->robj;
 
537
                break;
 
538
        case DB_STENCIL_WRITE_BASE:
 
539
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
540
                if (r) {
 
541
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
542
                                        "0x%04X\n", reg);
 
543
                        return -EINVAL;
 
544
                }
 
545
                track->db_s_write_offset = radeon_get_ib_value(p, idx);
 
546
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
547
                track->db_s_write_bo = reloc->robj;
 
548
                break;
 
549
        case VGT_STRMOUT_CONFIG:
 
550
                track->vgt_strmout_config = radeon_get_ib_value(p, idx);
 
551
                break;
 
552
        case VGT_STRMOUT_BUFFER_CONFIG:
 
553
                track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
 
554
                break;
 
555
        case CB_TARGET_MASK:
 
556
                track->cb_target_mask = radeon_get_ib_value(p, idx);
 
557
                break;
 
558
        case CB_SHADER_MASK:
 
559
                track->cb_shader_mask = radeon_get_ib_value(p, idx);
 
560
                break;
 
561
        case PA_SC_AA_CONFIG:
 
562
                tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
 
563
                track->nsamples = 1 << tmp;
 
564
                break;
 
565
        case CB_COLOR0_VIEW:
 
566
        case CB_COLOR1_VIEW:
 
567
        case CB_COLOR2_VIEW:
 
568
        case CB_COLOR3_VIEW:
 
569
        case CB_COLOR4_VIEW:
 
570
        case CB_COLOR5_VIEW:
 
571
        case CB_COLOR6_VIEW:
 
572
        case CB_COLOR7_VIEW:
 
573
                tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
 
574
                track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
 
575
                break;
 
576
        case CB_COLOR8_VIEW:
 
577
        case CB_COLOR9_VIEW:
 
578
        case CB_COLOR10_VIEW:
 
579
        case CB_COLOR11_VIEW:
 
580
                tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
 
581
                track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
 
582
                break;
 
583
        case CB_COLOR0_INFO:
 
584
        case CB_COLOR1_INFO:
 
585
        case CB_COLOR2_INFO:
 
586
        case CB_COLOR3_INFO:
 
587
        case CB_COLOR4_INFO:
 
588
        case CB_COLOR5_INFO:
 
589
        case CB_COLOR6_INFO:
 
590
        case CB_COLOR7_INFO:
 
591
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
592
                if (r) {
 
593
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
594
                                        "0x%04X\n", reg);
 
595
                        return -EINVAL;
 
596
                }
 
597
                tmp = (reg - CB_COLOR0_INFO) / 0x3c;
 
598
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
 
599
                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
 
600
                        ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
601
                        track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
602
                } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
 
603
                        ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
604
                        track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
605
                }
 
606
                break;
 
607
        case CB_COLOR8_INFO:
 
608
        case CB_COLOR9_INFO:
 
609
        case CB_COLOR10_INFO:
 
610
        case CB_COLOR11_INFO:
 
611
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
612
                if (r) {
 
613
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
614
                                        "0x%04X\n", reg);
 
615
                        return -EINVAL;
 
616
                }
 
617
                tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
 
618
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
 
619
                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
 
620
                        ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
621
                        track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
622
                } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
 
623
                        ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
624
                        track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
625
                }
 
626
                break;
 
627
        case CB_COLOR0_PITCH:
 
628
        case CB_COLOR1_PITCH:
 
629
        case CB_COLOR2_PITCH:
 
630
        case CB_COLOR3_PITCH:
 
631
        case CB_COLOR4_PITCH:
 
632
        case CB_COLOR5_PITCH:
 
633
        case CB_COLOR6_PITCH:
 
634
        case CB_COLOR7_PITCH:
 
635
                tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
 
636
                track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
 
637
                track->cb_color_pitch_idx[tmp] = idx;
 
638
                break;
 
639
        case CB_COLOR8_PITCH:
 
640
        case CB_COLOR9_PITCH:
 
641
        case CB_COLOR10_PITCH:
 
642
        case CB_COLOR11_PITCH:
 
643
                tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
 
644
                track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
 
645
                track->cb_color_pitch_idx[tmp] = idx;
 
646
                break;
 
647
        case CB_COLOR0_SLICE:
 
648
        case CB_COLOR1_SLICE:
 
649
        case CB_COLOR2_SLICE:
 
650
        case CB_COLOR3_SLICE:
 
651
        case CB_COLOR4_SLICE:
 
652
        case CB_COLOR5_SLICE:
 
653
        case CB_COLOR6_SLICE:
 
654
        case CB_COLOR7_SLICE:
 
655
                tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
 
656
                track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
 
657
                track->cb_color_slice_idx[tmp] = idx;
 
658
                break;
 
659
        case CB_COLOR8_SLICE:
 
660
        case CB_COLOR9_SLICE:
 
661
        case CB_COLOR10_SLICE:
 
662
        case CB_COLOR11_SLICE:
 
663
                tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
 
664
                track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
 
665
                track->cb_color_slice_idx[tmp] = idx;
 
666
                break;
 
667
        case CB_COLOR0_ATTRIB:
 
668
        case CB_COLOR1_ATTRIB:
 
669
        case CB_COLOR2_ATTRIB:
 
670
        case CB_COLOR3_ATTRIB:
 
671
        case CB_COLOR4_ATTRIB:
 
672
        case CB_COLOR5_ATTRIB:
 
673
        case CB_COLOR6_ATTRIB:
 
674
        case CB_COLOR7_ATTRIB:
 
675
        case CB_COLOR8_ATTRIB:
 
676
        case CB_COLOR9_ATTRIB:
 
677
        case CB_COLOR10_ATTRIB:
 
678
        case CB_COLOR11_ATTRIB:
 
679
                break;
 
680
        case CB_COLOR0_DIM:
 
681
        case CB_COLOR1_DIM:
 
682
        case CB_COLOR2_DIM:
 
683
        case CB_COLOR3_DIM:
 
684
        case CB_COLOR4_DIM:
 
685
        case CB_COLOR5_DIM:
 
686
        case CB_COLOR6_DIM:
 
687
        case CB_COLOR7_DIM:
 
688
                tmp = (reg - CB_COLOR0_DIM) / 0x3c;
 
689
                track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
 
690
                track->cb_color_dim_idx[tmp] = idx;
 
691
                break;
 
692
        case CB_COLOR8_DIM:
 
693
        case CB_COLOR9_DIM:
 
694
        case CB_COLOR10_DIM:
 
695
        case CB_COLOR11_DIM:
 
696
                tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
 
697
                track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
 
698
                track->cb_color_dim_idx[tmp] = idx;
 
699
                break;
 
700
        case CB_COLOR0_FMASK:
 
701
        case CB_COLOR1_FMASK:
 
702
        case CB_COLOR2_FMASK:
 
703
        case CB_COLOR3_FMASK:
 
704
        case CB_COLOR4_FMASK:
 
705
        case CB_COLOR5_FMASK:
 
706
        case CB_COLOR6_FMASK:
 
707
        case CB_COLOR7_FMASK:
 
708
                tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
 
709
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
710
                if (r) {
 
711
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
 
712
                        return -EINVAL;
 
713
                }
 
714
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
715
                track->cb_color_fmask_bo[tmp] = reloc->robj;
 
716
                break;
 
717
        case CB_COLOR0_CMASK:
 
718
        case CB_COLOR1_CMASK:
 
719
        case CB_COLOR2_CMASK:
 
720
        case CB_COLOR3_CMASK:
 
721
        case CB_COLOR4_CMASK:
 
722
        case CB_COLOR5_CMASK:
 
723
        case CB_COLOR6_CMASK:
 
724
        case CB_COLOR7_CMASK:
 
725
                tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
 
726
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
727
                if (r) {
 
728
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
 
729
                        return -EINVAL;
 
730
                }
 
731
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
732
                track->cb_color_cmask_bo[tmp] = reloc->robj;
 
733
                break;
 
734
        case CB_COLOR0_FMASK_SLICE:
 
735
        case CB_COLOR1_FMASK_SLICE:
 
736
        case CB_COLOR2_FMASK_SLICE:
 
737
        case CB_COLOR3_FMASK_SLICE:
 
738
        case CB_COLOR4_FMASK_SLICE:
 
739
        case CB_COLOR5_FMASK_SLICE:
 
740
        case CB_COLOR6_FMASK_SLICE:
 
741
        case CB_COLOR7_FMASK_SLICE:
 
742
                tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
 
743
                track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
 
744
                break;
 
745
        case CB_COLOR0_CMASK_SLICE:
 
746
        case CB_COLOR1_CMASK_SLICE:
 
747
        case CB_COLOR2_CMASK_SLICE:
 
748
        case CB_COLOR3_CMASK_SLICE:
 
749
        case CB_COLOR4_CMASK_SLICE:
 
750
        case CB_COLOR5_CMASK_SLICE:
 
751
        case CB_COLOR6_CMASK_SLICE:
 
752
        case CB_COLOR7_CMASK_SLICE:
 
753
                tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
 
754
                track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
 
755
                break;
 
756
        case CB_COLOR0_BASE:
 
757
        case CB_COLOR1_BASE:
 
758
        case CB_COLOR2_BASE:
 
759
        case CB_COLOR3_BASE:
 
760
        case CB_COLOR4_BASE:
 
761
        case CB_COLOR5_BASE:
 
762
        case CB_COLOR6_BASE:
 
763
        case CB_COLOR7_BASE:
 
764
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
765
                if (r) {
 
766
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
767
                                        "0x%04X\n", reg);
 
768
                        return -EINVAL;
 
769
                }
 
770
                tmp = (reg - CB_COLOR0_BASE) / 0x3c;
 
771
                track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
 
772
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
773
                track->cb_color_base_last[tmp] = ib[idx];
 
774
                track->cb_color_bo[tmp] = reloc->robj;
 
775
                break;
 
776
        case CB_COLOR8_BASE:
 
777
        case CB_COLOR9_BASE:
 
778
        case CB_COLOR10_BASE:
 
779
        case CB_COLOR11_BASE:
 
780
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
781
                if (r) {
 
782
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
783
                                        "0x%04X\n", reg);
 
784
                        return -EINVAL;
 
785
                }
 
786
                tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
 
787
                track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
 
788
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
789
                track->cb_color_base_last[tmp] = ib[idx];
 
790
                track->cb_color_bo[tmp] = reloc->robj;
 
791
                break;
 
792
        case CB_IMMED0_BASE:
 
793
        case CB_IMMED1_BASE:
 
794
        case CB_IMMED2_BASE:
 
795
        case CB_IMMED3_BASE:
 
796
        case CB_IMMED4_BASE:
 
797
        case CB_IMMED5_BASE:
 
798
        case CB_IMMED6_BASE:
 
799
        case CB_IMMED7_BASE:
 
800
        case CB_IMMED8_BASE:
 
801
        case CB_IMMED9_BASE:
 
802
        case CB_IMMED10_BASE:
 
803
        case CB_IMMED11_BASE:
 
804
        case DB_HTILE_DATA_BASE:
 
805
        case SQ_PGM_START_FS:
 
806
        case SQ_PGM_START_ES:
 
807
        case SQ_PGM_START_VS:
 
808
        case SQ_PGM_START_GS:
 
809
        case SQ_PGM_START_PS:
 
810
        case SQ_PGM_START_HS:
 
811
        case SQ_PGM_START_LS:
 
812
        case GDS_ADDR_BASE:
 
813
        case SQ_CONST_MEM_BASE:
 
814
        case SQ_ALU_CONST_CACHE_GS_0:
 
815
        case SQ_ALU_CONST_CACHE_GS_1:
 
816
        case SQ_ALU_CONST_CACHE_GS_2:
 
817
        case SQ_ALU_CONST_CACHE_GS_3:
 
818
        case SQ_ALU_CONST_CACHE_GS_4:
 
819
        case SQ_ALU_CONST_CACHE_GS_5:
 
820
        case SQ_ALU_CONST_CACHE_GS_6:
 
821
        case SQ_ALU_CONST_CACHE_GS_7:
 
822
        case SQ_ALU_CONST_CACHE_GS_8:
 
823
        case SQ_ALU_CONST_CACHE_GS_9:
 
824
        case SQ_ALU_CONST_CACHE_GS_10:
 
825
        case SQ_ALU_CONST_CACHE_GS_11:
 
826
        case SQ_ALU_CONST_CACHE_GS_12:
 
827
        case SQ_ALU_CONST_CACHE_GS_13:
 
828
        case SQ_ALU_CONST_CACHE_GS_14:
 
829
        case SQ_ALU_CONST_CACHE_GS_15:
 
830
        case SQ_ALU_CONST_CACHE_PS_0:
 
831
        case SQ_ALU_CONST_CACHE_PS_1:
 
832
        case SQ_ALU_CONST_CACHE_PS_2:
 
833
        case SQ_ALU_CONST_CACHE_PS_3:
 
834
        case SQ_ALU_CONST_CACHE_PS_4:
 
835
        case SQ_ALU_CONST_CACHE_PS_5:
 
836
        case SQ_ALU_CONST_CACHE_PS_6:
 
837
        case SQ_ALU_CONST_CACHE_PS_7:
 
838
        case SQ_ALU_CONST_CACHE_PS_8:
 
839
        case SQ_ALU_CONST_CACHE_PS_9:
 
840
        case SQ_ALU_CONST_CACHE_PS_10:
 
841
        case SQ_ALU_CONST_CACHE_PS_11:
 
842
        case SQ_ALU_CONST_CACHE_PS_12:
 
843
        case SQ_ALU_CONST_CACHE_PS_13:
 
844
        case SQ_ALU_CONST_CACHE_PS_14:
 
845
        case SQ_ALU_CONST_CACHE_PS_15:
 
846
        case SQ_ALU_CONST_CACHE_VS_0:
 
847
        case SQ_ALU_CONST_CACHE_VS_1:
 
848
        case SQ_ALU_CONST_CACHE_VS_2:
 
849
        case SQ_ALU_CONST_CACHE_VS_3:
 
850
        case SQ_ALU_CONST_CACHE_VS_4:
 
851
        case SQ_ALU_CONST_CACHE_VS_5:
 
852
        case SQ_ALU_CONST_CACHE_VS_6:
 
853
        case SQ_ALU_CONST_CACHE_VS_7:
 
854
        case SQ_ALU_CONST_CACHE_VS_8:
 
855
        case SQ_ALU_CONST_CACHE_VS_9:
 
856
        case SQ_ALU_CONST_CACHE_VS_10:
 
857
        case SQ_ALU_CONST_CACHE_VS_11:
 
858
        case SQ_ALU_CONST_CACHE_VS_12:
 
859
        case SQ_ALU_CONST_CACHE_VS_13:
 
860
        case SQ_ALU_CONST_CACHE_VS_14:
 
861
        case SQ_ALU_CONST_CACHE_VS_15:
 
862
        case SQ_ALU_CONST_CACHE_HS_0:
 
863
        case SQ_ALU_CONST_CACHE_HS_1:
 
864
        case SQ_ALU_CONST_CACHE_HS_2:
 
865
        case SQ_ALU_CONST_CACHE_HS_3:
 
866
        case SQ_ALU_CONST_CACHE_HS_4:
 
867
        case SQ_ALU_CONST_CACHE_HS_5:
 
868
        case SQ_ALU_CONST_CACHE_HS_6:
 
869
        case SQ_ALU_CONST_CACHE_HS_7:
 
870
        case SQ_ALU_CONST_CACHE_HS_8:
 
871
        case SQ_ALU_CONST_CACHE_HS_9:
 
872
        case SQ_ALU_CONST_CACHE_HS_10:
 
873
        case SQ_ALU_CONST_CACHE_HS_11:
 
874
        case SQ_ALU_CONST_CACHE_HS_12:
 
875
        case SQ_ALU_CONST_CACHE_HS_13:
 
876
        case SQ_ALU_CONST_CACHE_HS_14:
 
877
        case SQ_ALU_CONST_CACHE_HS_15:
 
878
        case SQ_ALU_CONST_CACHE_LS_0:
 
879
        case SQ_ALU_CONST_CACHE_LS_1:
 
880
        case SQ_ALU_CONST_CACHE_LS_2:
 
881
        case SQ_ALU_CONST_CACHE_LS_3:
 
882
        case SQ_ALU_CONST_CACHE_LS_4:
 
883
        case SQ_ALU_CONST_CACHE_LS_5:
 
884
        case SQ_ALU_CONST_CACHE_LS_6:
 
885
        case SQ_ALU_CONST_CACHE_LS_7:
 
886
        case SQ_ALU_CONST_CACHE_LS_8:
 
887
        case SQ_ALU_CONST_CACHE_LS_9:
 
888
        case SQ_ALU_CONST_CACHE_LS_10:
 
889
        case SQ_ALU_CONST_CACHE_LS_11:
 
890
        case SQ_ALU_CONST_CACHE_LS_12:
 
891
        case SQ_ALU_CONST_CACHE_LS_13:
 
892
        case SQ_ALU_CONST_CACHE_LS_14:
 
893
        case SQ_ALU_CONST_CACHE_LS_15:
 
894
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
895
                if (r) {
 
896
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
 
897
                                        "0x%04X\n", reg);
 
898
                        return -EINVAL;
 
899
                }
 
900
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
901
                break;
 
902
        default:
 
903
                dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 
904
                return -EINVAL;
 
905
        }
 
906
        return 0;
 
907
}
 
908
 
 
909
/**
 
910
 * evergreen_check_texture_resource() - check if register is authorized or not
 
911
 * @p: parser structure holding parsing context
 
912
 * @idx: index into the cs buffer
 
913
 * @texture: texture's bo structure
 
914
 * @mipmap: mipmap's bo structure
 
915
 *
 
916
 * This function will check that the resource has valid field and that
 
917
 * the texture and mipmap bo object are big enough to cover this resource.
 
918
 */
 
919
static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 
920
                                                   struct radeon_bo *texture,
 
921
                                                   struct radeon_bo *mipmap)
 
922
{
 
923
        /* XXX fill in */
 
924
        return 0;
 
925
}
 
926
 
 
927
static int evergreen_packet3_check(struct radeon_cs_parser *p,
 
928
                                   struct radeon_cs_packet *pkt)
 
929
{
 
930
        struct radeon_cs_reloc *reloc;
 
931
        struct evergreen_cs_track *track;
 
932
        volatile u32 *ib;
 
933
        unsigned idx;
 
934
        unsigned i;
 
935
        unsigned start_reg, end_reg, reg;
 
936
        int r;
 
937
        u32 idx_value;
 
938
 
 
939
        track = (struct evergreen_cs_track *)p->track;
 
940
        ib = p->ib->ptr;
 
941
        idx = pkt->idx + 1;
 
942
        idx_value = radeon_get_ib_value(p, idx);
 
943
 
 
944
        switch (pkt->opcode) {
 
945
        case PACKET3_CONTEXT_CONTROL:
 
946
                if (pkt->count != 1) {
 
947
                        DRM_ERROR("bad CONTEXT_CONTROL\n");
 
948
                        return -EINVAL;
 
949
                }
 
950
                break;
 
951
        case PACKET3_INDEX_TYPE:
 
952
        case PACKET3_NUM_INSTANCES:
 
953
        case PACKET3_CLEAR_STATE:
 
954
                if (pkt->count) {
 
955
                        DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
 
956
                        return -EINVAL;
 
957
                }
 
958
                break;
 
959
        case PACKET3_INDEX_BASE:
 
960
                if (pkt->count != 1) {
 
961
                        DRM_ERROR("bad INDEX_BASE\n");
 
962
                        return -EINVAL;
 
963
                }
 
964
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
965
                if (r) {
 
966
                        DRM_ERROR("bad INDEX_BASE\n");
 
967
                        return -EINVAL;
 
968
                }
 
969
                ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
970
                ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
971
                r = evergreen_cs_track_check(p);
 
972
                if (r) {
 
973
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
974
                        return r;
 
975
                }
 
976
                break;
 
977
        case PACKET3_DRAW_INDEX:
 
978
                if (pkt->count != 3) {
 
979
                        DRM_ERROR("bad DRAW_INDEX\n");
 
980
                        return -EINVAL;
 
981
                }
 
982
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
983
                if (r) {
 
984
                        DRM_ERROR("bad DRAW_INDEX\n");
 
985
                        return -EINVAL;
 
986
                }
 
987
                ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
988
                ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
989
                r = evergreen_cs_track_check(p);
 
990
                if (r) {
 
991
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
992
                        return r;
 
993
                }
 
994
                break;
 
995
        case PACKET3_DRAW_INDEX_2:
 
996
                if (pkt->count != 4) {
 
997
                        DRM_ERROR("bad DRAW_INDEX_2\n");
 
998
                        return -EINVAL;
 
999
                }
 
1000
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1001
                if (r) {
 
1002
                        DRM_ERROR("bad DRAW_INDEX_2\n");
 
1003
                        return -EINVAL;
 
1004
                }
 
1005
                ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
1006
                ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1007
                r = evergreen_cs_track_check(p);
 
1008
                if (r) {
 
1009
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
1010
                        return r;
 
1011
                }
 
1012
                break;
 
1013
        case PACKET3_DRAW_INDEX_AUTO:
 
1014
                if (pkt->count != 1) {
 
1015
                        DRM_ERROR("bad DRAW_INDEX_AUTO\n");
 
1016
                        return -EINVAL;
 
1017
                }
 
1018
                r = evergreen_cs_track_check(p);
 
1019
                if (r) {
 
1020
                        dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
 
1021
                        return r;
 
1022
                }
 
1023
                break;
 
1024
        case PACKET3_DRAW_INDEX_MULTI_AUTO:
 
1025
                if (pkt->count != 2) {
 
1026
                        DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
 
1027
                        return -EINVAL;
 
1028
                }
 
1029
                r = evergreen_cs_track_check(p);
 
1030
                if (r) {
 
1031
                        dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
 
1032
                        return r;
 
1033
                }
 
1034
                break;
 
1035
        case PACKET3_DRAW_INDEX_IMMD:
 
1036
                if (pkt->count < 2) {
 
1037
                        DRM_ERROR("bad DRAW_INDEX_IMMD\n");
 
1038
                        return -EINVAL;
 
1039
                }
 
1040
                r = evergreen_cs_track_check(p);
 
1041
                if (r) {
 
1042
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
1043
                        return r;
 
1044
                }
 
1045
                break;
 
1046
        case PACKET3_DRAW_INDEX_OFFSET:
 
1047
                if (pkt->count != 2) {
 
1048
                        DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
 
1049
                        return -EINVAL;
 
1050
                }
 
1051
                r = evergreen_cs_track_check(p);
 
1052
                if (r) {
 
1053
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
1054
                        return r;
 
1055
                }
 
1056
                break;
 
1057
        case PACKET3_DRAW_INDEX_OFFSET_2:
 
1058
                if (pkt->count != 3) {
 
1059
                        DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
 
1060
                        return -EINVAL;
 
1061
                }
 
1062
                r = evergreen_cs_track_check(p);
 
1063
                if (r) {
 
1064
                        dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
 
1065
                        return r;
 
1066
                }
 
1067
                break;
 
1068
        case PACKET3_WAIT_REG_MEM:
 
1069
                if (pkt->count != 5) {
 
1070
                        DRM_ERROR("bad WAIT_REG_MEM\n");
 
1071
                        return -EINVAL;
 
1072
                }
 
1073
                /* bit 4 is reg (0) or mem (1) */
 
1074
                if (idx_value & 0x10) {
 
1075
                        r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1076
                        if (r) {
 
1077
                                DRM_ERROR("bad WAIT_REG_MEM\n");
 
1078
                                return -EINVAL;
 
1079
                        }
 
1080
                        ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
1081
                        ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1082
                }
 
1083
                break;
 
1084
        case PACKET3_SURFACE_SYNC:
 
1085
                if (pkt->count != 3) {
 
1086
                        DRM_ERROR("bad SURFACE_SYNC\n");
 
1087
                        return -EINVAL;
 
1088
                }
 
1089
                /* 0xffffffff/0x0 is flush all cache flag */
 
1090
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
 
1091
                    radeon_get_ib_value(p, idx + 2) != 0) {
 
1092
                        r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1093
                        if (r) {
 
1094
                                DRM_ERROR("bad SURFACE_SYNC\n");
 
1095
                                return -EINVAL;
 
1096
                        }
 
1097
                        ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
1098
                }
 
1099
                break;
 
1100
        case PACKET3_EVENT_WRITE:
 
1101
                if (pkt->count != 2 && pkt->count != 0) {
 
1102
                        DRM_ERROR("bad EVENT_WRITE\n");
 
1103
                        return -EINVAL;
 
1104
                }
 
1105
                if (pkt->count) {
 
1106
                        r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1107
                        if (r) {
 
1108
                                DRM_ERROR("bad EVENT_WRITE\n");
 
1109
                                return -EINVAL;
 
1110
                        }
 
1111
                        ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
1112
                        ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1113
                }
 
1114
                break;
 
1115
        case PACKET3_EVENT_WRITE_EOP:
 
1116
                if (pkt->count != 4) {
 
1117
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
 
1118
                        return -EINVAL;
 
1119
                }
 
1120
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1121
                if (r) {
 
1122
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
 
1123
                        return -EINVAL;
 
1124
                }
 
1125
                ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
1126
                ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1127
                break;
 
1128
        case PACKET3_EVENT_WRITE_EOS:
 
1129
                if (pkt->count != 3) {
 
1130
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
 
1131
                        return -EINVAL;
 
1132
                }
 
1133
                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1134
                if (r) {
 
1135
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
 
1136
                        return -EINVAL;
 
1137
                }
 
1138
                ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 
1139
                ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1140
                break;
 
1141
        case PACKET3_SET_CONFIG_REG:
 
1142
                start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
 
1143
                end_reg = 4 * pkt->count + start_reg - 4;
 
1144
                if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
 
1145
                    (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
 
1146
                    (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
 
1147
                        DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
 
1148
                        return -EINVAL;
 
1149
                }
 
1150
                for (i = 0; i < pkt->count; i++) {
 
1151
                        reg = start_reg + (4 * i);
 
1152
                        r = evergreen_cs_check_reg(p, reg, idx+1+i);
 
1153
                        if (r)
 
1154
                                return r;
 
1155
                }
 
1156
                break;
 
1157
        case PACKET3_SET_CONTEXT_REG:
 
1158
                start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
 
1159
                end_reg = 4 * pkt->count + start_reg - 4;
 
1160
                if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
 
1161
                    (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
 
1162
                    (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
 
1163
                        DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
 
1164
                        return -EINVAL;
 
1165
                }
 
1166
                for (i = 0; i < pkt->count; i++) {
 
1167
                        reg = start_reg + (4 * i);
 
1168
                        r = evergreen_cs_check_reg(p, reg, idx+1+i);
 
1169
                        if (r)
 
1170
                                return r;
 
1171
                }
 
1172
                break;
 
1173
        case PACKET3_SET_RESOURCE:
 
1174
                if (pkt->count % 8) {
 
1175
                        DRM_ERROR("bad SET_RESOURCE\n");
 
1176
                        return -EINVAL;
 
1177
                }
 
1178
                start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
 
1179
                end_reg = 4 * pkt->count + start_reg - 4;
 
1180
                if ((start_reg < PACKET3_SET_RESOURCE_START) ||
 
1181
                    (start_reg >= PACKET3_SET_RESOURCE_END) ||
 
1182
                    (end_reg >= PACKET3_SET_RESOURCE_END)) {
 
1183
                        DRM_ERROR("bad SET_RESOURCE\n");
 
1184
                        return -EINVAL;
 
1185
                }
 
1186
                for (i = 0; i < (pkt->count / 8); i++) {
 
1187
                        struct radeon_bo *texture, *mipmap;
 
1188
                        u32 size, offset;
 
1189
 
 
1190
                        switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
 
1191
                        case SQ_TEX_VTX_VALID_TEXTURE:
 
1192
                                /* tex base */
 
1193
                                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1194
                                if (r) {
 
1195
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
 
1196
                                        return -EINVAL;
 
1197
                                }
 
1198
                                ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
1199
                                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 
1200
                                        ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
 
1201
                                else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 
1202
                                        ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
 
1203
                                texture = reloc->robj;
 
1204
                                /* tex mip base */
 
1205
                                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1206
                                if (r) {
 
1207
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
 
1208
                                        return -EINVAL;
 
1209
                                }
 
1210
                                ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 
1211
                                mipmap = reloc->robj;
 
1212
                                r = evergreen_check_texture_resource(p,  idx+1+(i*8),
 
1213
                                                texture, mipmap);
 
1214
                                if (r)
 
1215
                                        return r;
 
1216
                                break;
 
1217
                        case SQ_TEX_VTX_VALID_BUFFER:
 
1218
                                /* vtx base */
 
1219
                                r = evergreen_cs_packet_next_reloc(p, &reloc);
 
1220
                                if (r) {
 
1221
                                        DRM_ERROR("bad SET_RESOURCE (vtx)\n");
 
1222
                                        return -EINVAL;
 
1223
                                }
 
1224
                                offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
 
1225
                                size = radeon_get_ib_value(p, idx+1+(i*8)+1);
 
1226
                                if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
 
1227
                                        /* force size to size of the buffer */
 
1228
                                        dev_warn(p->dev, "vbo resource seems too big for the bo\n");
 
1229
                                        ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
 
1230
                                }
 
1231
                                ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
 
1232
                                ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 
1233
                                break;
 
1234
                        case SQ_TEX_VTX_INVALID_TEXTURE:
 
1235
                        case SQ_TEX_VTX_INVALID_BUFFER:
 
1236
                        default:
 
1237
                                DRM_ERROR("bad SET_RESOURCE\n");
 
1238
                                return -EINVAL;
 
1239
                        }
 
1240
                }
 
1241
                break;
 
1242
        case PACKET3_SET_ALU_CONST:
 
1243
                /* XXX fix me ALU const buffers only */
 
1244
                break;
 
1245
        case PACKET3_SET_BOOL_CONST:
 
1246
                start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
 
1247
                end_reg = 4 * pkt->count + start_reg - 4;
 
1248
                if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
 
1249
                    (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
 
1250
                    (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
 
1251
                        DRM_ERROR("bad SET_BOOL_CONST\n");
 
1252
                        return -EINVAL;
 
1253
                }
 
1254
                break;
 
1255
        case PACKET3_SET_LOOP_CONST:
 
1256
                start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
 
1257
                end_reg = 4 * pkt->count + start_reg - 4;
 
1258
                if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
 
1259
                    (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
 
1260
                    (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
 
1261
                        DRM_ERROR("bad SET_LOOP_CONST\n");
 
1262
                        return -EINVAL;
 
1263
                }
 
1264
                break;
 
1265
        case PACKET3_SET_CTL_CONST:
 
1266
                start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
 
1267
                end_reg = 4 * pkt->count + start_reg - 4;
 
1268
                if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
 
1269
                    (start_reg >= PACKET3_SET_CTL_CONST_END) ||
 
1270
                    (end_reg >= PACKET3_SET_CTL_CONST_END)) {
 
1271
                        DRM_ERROR("bad SET_CTL_CONST\n");
 
1272
                        return -EINVAL;
 
1273
                }
 
1274
                break;
 
1275
        case PACKET3_SET_SAMPLER:
 
1276
                if (pkt->count % 3) {
 
1277
                        DRM_ERROR("bad SET_SAMPLER\n");
 
1278
                        return -EINVAL;
 
1279
                }
 
1280
                start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
 
1281
                end_reg = 4 * pkt->count + start_reg - 4;
 
1282
                if ((start_reg < PACKET3_SET_SAMPLER_START) ||
 
1283
                    (start_reg >= PACKET3_SET_SAMPLER_END) ||
 
1284
                    (end_reg >= PACKET3_SET_SAMPLER_END)) {
 
1285
                        DRM_ERROR("bad SET_SAMPLER\n");
 
1286
                        return -EINVAL;
 
1287
                }
 
1288
                break;
 
1289
        case PACKET3_NOP:
 
1290
                break;
 
1291
        default:
 
1292
                DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
 
1293
                return -EINVAL;
 
1294
        }
 
1295
        return 0;
 
1296
}
 
1297
 
 
1298
int evergreen_cs_parse(struct radeon_cs_parser *p)
 
1299
{
 
1300
        struct radeon_cs_packet pkt;
 
1301
        struct evergreen_cs_track *track;
 
1302
        int r;
 
1303
 
 
1304
        if (p->track == NULL) {
 
1305
                /* initialize tracker, we are in kms */
 
1306
                track = kzalloc(sizeof(*track), GFP_KERNEL);
 
1307
                if (track == NULL)
 
1308
                        return -ENOMEM;
 
1309
                evergreen_cs_track_init(track);
 
1310
                track->npipes = p->rdev->config.evergreen.tiling_npipes;
 
1311
                track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
 
1312
                track->group_size = p->rdev->config.evergreen.tiling_group_size;
 
1313
                p->track = track;
 
1314
        }
 
1315
        do {
 
1316
                r = evergreen_cs_packet_parse(p, &pkt, p->idx);
 
1317
                if (r) {
 
1318
                        kfree(p->track);
 
1319
                        p->track = NULL;
 
1320
                        return r;
 
1321
                }
 
1322
                p->idx += pkt.count + 2;
 
1323
                switch (pkt.type) {
 
1324
                case PACKET_TYPE0:
 
1325
                        r = evergreen_cs_parse_packet0(p, &pkt);
 
1326
                        break;
 
1327
                case PACKET_TYPE2:
 
1328
                        break;
 
1329
                case PACKET_TYPE3:
 
1330
                        r = evergreen_packet3_check(p, &pkt);
 
1331
                        break;
 
1332
                default:
 
1333
                        DRM_ERROR("Unknown packet type %d !\n", pkt.type);
 
1334
                        kfree(p->track);
 
1335
                        p->track = NULL;
 
1336
                        return -EINVAL;
 
1337
                }
 
1338
                if (r) {
 
1339
                        kfree(p->track);
 
1340
                        p->track = NULL;
 
1341
                        return r;
 
1342
                }
 
1343
        } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
 
1344
#if 0
 
1345
        for (r = 0; r < p->ib->length_dw; r++) {
 
1346
                printk(KERN_INFO "%05d  0x%08X\n", r, p->ib->ptr[r]);
 
1347
                mdelay(1);
 
1348
        }
 
1349
#endif
 
1350
        kfree(p->track);
 
1351
        p->track = NULL;
 
1352
        return 0;
 
1353
}
 
1354