blob: cd99302531a6673516922308ebf3852925dc6098 [file] [log] [blame]
Jordan Crousea78c9172011-07-11 13:14:09 -06001/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include "kgsl.h"
15#include "kgsl_sharedmem.h"
16#include "kgsl_cffdump.h"
17#include "adreno.h"
18
19/*
20 *
21 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
22 * (34.5KB)
23 *
24 * +---------------------+------------+-------------+---+---------------------+
25 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
26 * +---------------------+------------+-------------+---+---------------------+
27 * ________________________________/ \____________________
28 * / |
29 * +--------------+-----------+------+-----------+------------------------+
30 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
31 * +--------------+-----------+------+-----------+------------------------+
32 *
33 * 8K - ALU Constant Shadow (8K aligned)
34 * 4K - H/W Register Shadow (8K aligned)
35 * 4K - Command and Vertex Buffers
36 * - Indirect command buffer : Const/Reg restore
37 * - includes Loop & Bool const shadows
38 * - Indirect command buffer : Const/Reg save
39 * - Quad vertices & texture coordinates
40 * - Indirect command buffer : Gmem save
41 * - Indirect command buffer : Gmem restore
42 * - Unused (padding to 8KB boundary)
43 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
44 * 18K - Shader Instruction Shadow
45 * - 6K vertex (32 byte aligned)
46 * - 6K pixel (32 byte aligned)
47 * - 6K shared (32 byte aligned)
48 *
49 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
50 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
51 * 16 bytes per constant. If the texture constants were transfered this way,
52 * the Command & Vertex Buffers section would extend past the 16K boundary.
53 * By moving the texture constant shadow area to start at 16KB boundary, we
54 * only require approximately 40 bytes more memory, but are able to use the
55 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
56 * context switching.
57 *
58 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
59 * constants would require an additional 8KB each, for alignment.]
60 *
61 */
62
63/* Constants */
64
65#define ALU_CONSTANTS 2048 /* DWORDS */
66#define NUM_REGISTERS 1024 /* DWORDS */
67#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
68#define CMD_BUFFER_LEN 9216 /* DWORDS */
69#else
70#define CMD_BUFFER_LEN 3072 /* DWORDS */
71#endif
72#define TEX_CONSTANTS (32*6) /* DWORDS */
73#define BOOL_CONSTANTS 8 /* DWORDS */
74#define LOOP_CONSTANTS 56 /* DWORDS */
75#define SHADER_INSTRUCT_LOG2 9U /* 2^n == SHADER_INSTRUCTIONS */
76
77#if defined(PM4_IM_STORE)
78/* 96-bit instructions */
79#define SHADER_INSTRUCT (1<<SHADER_INSTRUCT_LOG2)
80#else
81#define SHADER_INSTRUCT 0
82#endif
83
84/* LOAD_CONSTANT_CONTEXT shadow size */
85#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
86
87#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
88#define REG_SHADOW_SIZE 0x1000 /* 4KB */
89#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
90#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
91#else
92#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
93#endif
94#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
95#define SHADER_SHADOW_SIZE (SHADER_INSTRUCT*12) /* 6KB */
96
97#define REG_OFFSET LCC_SHADOW_SIZE
98#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
99#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
100#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
101
102#define CONTEXT_SIZE (SHADER_OFFSET + 3 * SHADER_SHADOW_SIZE)
103
104/* A scratchpad used to build commands during context create */
105
106static struct tmp_ctx {
107 unsigned int *start; /* Command & Vertex buffer start */
108 unsigned int *cmd; /* Next available dword in C&V buffer */
109
110 /* address of buffers, needed when creating IB1 command buffers. */
111 uint32_t bool_shadow; /* bool constants */
112 uint32_t loop_shadow; /* loop constants */
113
114#if defined(PM4_IM_STORE)
115 uint32_t shader_shared; /* shared shader instruction shadow */
116 uint32_t shader_vertex; /* vertex shader instruction shadow */
117 uint32_t shader_pixel; /* pixel shader instruction shadow */
118#endif
119
120 /* Addresses in command buffer where separately handled registers
121 * are saved
122 */
123 uint32_t reg_values[33];
124 uint32_t chicken_restore;
125
126 uint32_t gmem_base; /* Base gpu address of GMEM */
127
128} tmp_ctx;
129
130/* context save (gmem -> sys) */
131
132/* pre-compiled vertex shader program
133*
134* attribute vec4 P;
135* void main(void)
136* {
137* gl_Position = P;
138* }
139*/
140#define GMEM2SYS_VTX_PGM_LEN 0x12
141
142static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
143 0x00011003, 0x00001000, 0xc2000000,
144 0x00001004, 0x00001000, 0xc4000000,
145 0x00001005, 0x00002000, 0x00000000,
146 0x1cb81000, 0x00398a88, 0x00000003,
147 0x140f803e, 0x00000000, 0xe2010100,
148 0x14000000, 0x00000000, 0xe2000000
149};
150
151/* pre-compiled fragment shader program
152*
153* precision highp float;
154* uniform vec4 clear_color;
155* void main(void)
156* {
157* gl_FragColor = clear_color;
158* }
159*/
160
161#define GMEM2SYS_FRAG_PGM_LEN 0x0c
162
163static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
164 0x00000000, 0x1002c400, 0x10000000,
165 0x00001003, 0x00002000, 0x00000000,
166 0x140f8000, 0x00000000, 0x22000000,
167 0x14000000, 0x00000000, 0xe2000000
168};
169
170/* context restore (sys -> gmem) */
171/* pre-compiled vertex shader program
172*
173* attribute vec4 position;
174* attribute vec4 texcoord;
175* varying vec4 texcoord0;
176* void main()
177* {
178* gl_Position = position;
179* texcoord0 = texcoord;
180* }
181*/
182
183#define SYS2GMEM_VTX_PGM_LEN 0x18
184
185static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
186 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
187 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
188 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
189 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
190 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
191 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
192};
193
194/* pre-compiled fragment shader program
195*
196* precision mediump float;
197* uniform sampler2D tex0;
198* varying vec4 texcoord0;
199* void main()
200* {
201* gl_FragColor = texture2D(tex0, texcoord0.xy);
202* }
203*/
204
205#define SYS2GMEM_FRAG_PGM_LEN 0x0f
206
207static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
208 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
209 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
210 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
211 0x14000000, 0x00000000, 0xe2000000
212};
213
214/* shader texture constants (sysmem -> gmem) */
215#define SYS2GMEM_TEX_CONST_LEN 6
216
217static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
218 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
219 * RFMode=ZeroClamp-1, Dim=1:2d
220 */
221 0x00000002, /* Pitch = TBD */
222
223 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
224 * NearestClamp=1:OGL Mode
225 */
226 0x00000800, /* Address[31:12] = TBD */
227
228 /* Width, Height, EndianSwap=0:None */
229 0, /* Width & Height = TBD */
230
231 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
232 * Mip=2:BaseMap
233 */
234 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
235
236 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
237 * Dim3d=0
238 */
239 0,
240
241 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
242 * Dim=1:2d, MipPacking=0
243 */
244 1 << 9 /* Mip Address[31:12] = TBD */
245};
246
247/* quad for copying GMEM to context shadow */
248#define QUAD_LEN 12
249
250static unsigned int gmem_copy_quad[QUAD_LEN] = {
251 0x00000000, 0x00000000, 0x3f800000,
252 0x00000000, 0x00000000, 0x3f800000,
253 0x00000000, 0x00000000, 0x3f800000,
254 0x00000000, 0x00000000, 0x3f800000
255};
256
257#define TEXCOORD_LEN 8
258
259static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = {
260 0x00000000, 0x3f800000,
261 0x3f800000, 0x3f800000,
262 0x00000000, 0x00000000,
263 0x3f800000, 0x00000000
264};
265
266#define NUM_COLOR_FORMATS 13
267
268static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
269 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
270 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
271 FMT_5_6_5, /* COLORX_5_6_5 */
272 FMT_8, /* COLORX_8 */
273 FMT_8_8, /* COLORX_8_8 */
274 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
275 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
276 FMT_16_FLOAT, /* COLORX_16_FLOAT */
277 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
278 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
279 FMT_32_FLOAT, /* COLORX_32_FLOAT */
280 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
281 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
282};
283
284static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
285 2, /* COLORX_4_4_4_4 */
286 2, /* COLORX_1_5_5_5 */
287 2, /* COLORX_5_6_5 */
288 1, /* COLORX_8 */
289 2, /* COLORX_8_8 8*/
290 4, /* COLORX_8_8_8_8 */
291 4, /* COLORX_S8_8_8_8 */
292 2, /* COLORX_16_FLOAT */
293 4, /* COLORX_16_16_FLOAT */
294 8, /* COLORX_16_16_16_16_FLOAT */
295 4, /* COLORX_32_FLOAT */
296 8, /* COLORX_32_32_FLOAT */
297 16, /* COLORX_32_32_32_32_FLOAT */
298};
299
300/* shader linkage info */
301#define SHADER_CONST_ADDR (11 * 6 + 3)
302
303/* gmem command buffer length */
304#define PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg)))
305
306/* functions */
307static void config_gmemsize(struct gmem_shadow_t *shadow, int gmem_size)
308{
309 int w = 64, h = 64; /* 16KB surface, minimum */
310
311 shadow->format = COLORX_8_8_8_8;
312 /* convert from bytes to 32-bit words */
313 gmem_size = (gmem_size + 3) / 4;
314
315 /* find the right surface size, close to a square. */
316 while (w * h < gmem_size)
317 if (w < h)
318 w *= 2;
319 else
320 h *= 2;
321
322 shadow->width = w;
323 shadow->pitch = w;
324 shadow->height = h;
325 shadow->gmem_pitch = shadow->pitch;
326
327 shadow->size = shadow->pitch * shadow->height * 4;
328}
329
330static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
331 unsigned int *shader_pgm, int dwords)
332{
333 /* load the patched vertex shader stream */
334 *cmds++ = pm4_type3_packet(PM4_IM_LOAD_IMMEDIATE, 2 + dwords);
335 /* 0=vertex shader, 1=fragment shader */
336 *cmds++ = vtxfrag;
337 /* instruction start & size (in 32-bit words) */
338 *cmds++ = ((0 << 16) | dwords);
339
340 memcpy(cmds, shader_pgm, dwords << 2);
341 cmds += dwords;
342
343 return cmds;
344}
345
346static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
347 uint32_t src, int dwords)
348{
349 while (dwords-- > 0) {
350 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
351 *cmds++ = src++;
352 *cmds++ = dst;
353 dst += 4;
354 }
355
356 return cmds;
357}
358
359#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
360
361static void build_reg_to_mem_range(unsigned int start, unsigned int end,
362 unsigned int **cmd,
363 struct adreno_context *drawctxt)
364{
365 unsigned int i = start;
366
367 for (i = start; i <= end; i++) {
368 *(*cmd)++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
369 *(*cmd)++ = i;
370 *(*cmd)++ =
371 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
372 (i - 0x2000) * 4;
373 }
374}
375
376#endif
377
378/* chicken restore */
379static unsigned int *build_chicken_restore_cmds(
380 struct adreno_context *drawctxt)
381{
382 unsigned int *start = tmp_ctx.cmd;
383 unsigned int *cmds = start;
384
385 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
386 *cmds++ = 0;
387
388 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
389 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
390 *cmds++ = 0x00000000;
391
392 /* create indirect buffer command for above command sequence */
393 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
394
395 return cmds;
396}
397
398/****************************************************************************/
399/* context save */
400/****************************************************************************/
401
402static const unsigned int register_ranges_a20x[] = {
403 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
404 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
405 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
406 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
407 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
408 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
409 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
410 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
411 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
412 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
413 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
414 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
415 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
416 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
417};
418
419static const unsigned int register_ranges_a22x[] = {
420 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
421 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
422 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
423 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
424 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
425 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
426 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
427 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
428 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
429 /* all the below registers are specific to Leia */
430 REG_LEIA_PC_MAX_VTX_INDX, REG_LEIA_PC_INDX_OFFSET,
431 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
432 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
433 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
434 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
435 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
436 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
437 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
438 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
439};
440
441
442/* save h/w regs, alu constants, texture contants, etc. ...
443* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
444*/
445static void build_regsave_cmds(struct adreno_device *adreno_dev,
446 struct adreno_context *drawctxt)
447{
448 unsigned int *start = tmp_ctx.cmd;
449 unsigned int *cmd = start;
450
451 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
452 *cmd++ = 0;
453
454#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
455 /* Make sure the HW context has the correct register values
456 * before reading them. */
457 *cmd++ = pm4_type3_packet(PM4_CONTEXT_UPDATE, 1);
458 *cmd++ = 0;
459
460 {
461 unsigned int i = 0;
462 unsigned int reg_array_size = 0;
463 const unsigned int *ptr_register_ranges;
464
465 /* Based on chip id choose the register ranges */
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600466 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600467 ptr_register_ranges = register_ranges_a22x;
468 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
469 } else {
470 ptr_register_ranges = register_ranges_a20x;
471 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
472 }
473
474
475 /* Write HW registers into shadow */
476 for (i = 0; i < (reg_array_size/2) ; i++) {
477 build_reg_to_mem_range(ptr_register_ranges[i*2],
478 ptr_register_ranges[i*2+1],
479 &cmd, drawctxt);
480 }
481 }
482
483 /* Copy ALU constants */
484 cmd =
485 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
486 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
487
488 /* Copy Tex constants */
489 cmd =
490 reg_to_mem(cmd,
491 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
492 REG_SQ_FETCH_0, TEX_CONSTANTS);
493#else
494
495 /* Insert a wait for idle packet before reading the registers.
496 * This is to fix a hang/reset seen during stress testing. In this
497 * hang, CP encountered a timeout reading SQ's boolean constant
498 * register. There is logic in the HW that blocks reading of this
499 * register when the SQ block is not idle, which we believe is
500 * contributing to the hang.*/
501 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
502 *cmd++ = 0;
503
504 /* H/w registers are already shadowed; just need to disable shadowing
505 * to prevent corruption.
506 */
507 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
508 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
509 *cmd++ = 4 << 16; /* regs, start=0 */
510 *cmd++ = 0x0; /* count = 0 */
511
512 /* ALU constants are already shadowed; just need to disable shadowing
513 * to prevent corruption.
514 */
515 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
516 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
517 *cmd++ = 0 << 16; /* ALU, start=0 */
518 *cmd++ = 0x0; /* count = 0 */
519
520 /* Tex constants are already shadowed; just need to disable shadowing
521 * to prevent corruption.
522 */
523 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
524 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
525 *cmd++ = 1 << 16; /* Tex, start=0 */
526 *cmd++ = 0x0; /* count = 0 */
527#endif
528
529 /* Need to handle some of the registers separately */
530 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
531 *cmd++ = REG_SQ_GPR_MANAGEMENT;
532 *cmd++ = tmp_ctx.reg_values[0];
533
534 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
535 *cmd++ = REG_TP0_CHICKEN;
536 *cmd++ = tmp_ctx.reg_values[1];
537
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600538 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600539 unsigned int i;
540 unsigned int j = 2;
541 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
542 REG_LEIA_VSC_PIPE_DATA_LENGTH_7; i++) {
543 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
544 *cmd++ = i;
545 *cmd++ = tmp_ctx.reg_values[j];
546 j++;
547 }
548 }
549
550 /* Copy Boolean constants */
551 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
552 BOOL_CONSTANTS);
553
554 /* Copy Loop constants */
555 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
556 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
557
558 /* create indirect buffer command for above command sequence */
559 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
560
561 tmp_ctx.cmd = cmd;
562}
563
564/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
565static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
566 struct adreno_context *drawctxt,
567 struct gmem_shadow_t *shadow)
568{
569 unsigned int *cmds = shadow->gmem_save_commands;
570 unsigned int *start = cmds;
571 /* Calculate the new offset based on the adjusted base */
572 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
573 unsigned int addr = shadow->gmemshadow.gpuaddr;
574 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
575
576 /* Store TP0_CHICKEN register */
577 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
578 *cmds++ = REG_TP0_CHICKEN;
579
580 *cmds++ = tmp_ctx.chicken_restore;
581
582 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
583 *cmds++ = 0;
584
585 /* Set TP0_CHICKEN to zero */
586 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
587 *cmds++ = 0x00000000;
588
589 /* Set PA_SC_AA_CONFIG to 0 */
590 *cmds++ = pm4_type0_packet(REG_PA_SC_AA_CONFIG, 1);
591 *cmds++ = 0x00000000;
592
593 /* program shader */
594
595 /* load shader vtx constants ... 5 dwords */
596 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
597 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
598 *cmds++ = 0;
599 /* valid(?) vtx constant flag & addr */
600 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
601 /* limit = 12 dwords */
602 *cmds++ = 0x00000030;
603
604 /* Invalidate L2 cache to make sure vertices are updated */
605 *cmds++ = pm4_type0_packet(REG_TC_CNTL_STATUS, 1);
606 *cmds++ = 0x1;
607
608 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
609 *cmds++ = PM4_REG(REG_VGT_MAX_VTX_INDX);
610 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
611 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
612 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
613
614 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
615 *cmds++ = PM4_REG(REG_PA_SC_AA_MASK);
616 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
617
618 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
619 *cmds++ = PM4_REG(REG_RB_COLORCONTROL);
620 *cmds++ = 0x00000c20;
621
Tarun Karra16346b02011-07-24 15:04:26 -0700622 /* Repartition shaders */
623 *cmds++ = pm4_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
624 *cmds++ = 0x180;
625
626 /* Invalidate Vertex & Pixel instruction code address and sizes */
627 *cmds++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1);
628 *cmds++ = 0x00003F00;
629
630 *cmds++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1);
631 *cmds++ = (0x80000000) | 0x180;
632
Jordan Crousea78c9172011-07-11 13:14:09 -0600633 /* load the patched vertex shader stream */
634 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
635
636 /* Load the patched fragment shader stream */
637 cmds =
638 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
639
640 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
641 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
642 *cmds++ = PM4_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600643 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600644 *cmds++ = 0x10018001;
645 else
646 *cmds++ = 0x10010001;
647 *cmds++ = 0x00000008;
648
649 /* resolve */
650
651 /* PA_CL_VTE_CNTL */
652 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
653 *cmds++ = PM4_REG(REG_PA_CL_VTE_CNTL);
654 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
655 *cmds++ = 0x00000b00;
656
657 /* program surface info */
658 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
659 *cmds++ = PM4_REG(REG_RB_SURFACE_INFO);
660 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
661
662 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
663 * Base=gmem_base
664 */
665 /* gmem base assumed 4K aligned. */
666 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
667 *cmds++ =
668 (shadow->
669 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
670
671 /* disable Z */
672 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
673 *cmds++ = PM4_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600674 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600675 *cmds++ = 0x08;
676 else
677 *cmds++ = 0;
678
679 /* set REG_PA_SU_SC_MODE_CNTL
680 * Front_ptype = draw triangles
681 * Back_ptype = draw triangles
682 * Provoking vertex = last
683 */
684 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
685 *cmds++ = PM4_REG(REG_PA_SU_SC_MODE_CNTL);
686 *cmds++ = 0x00080240;
687
688 /* Use maximum scissor values -- quad vertices already have the
689 * correct bounds */
690 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
691 *cmds++ = PM4_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
692 *cmds++ = (0 << 16) | 0;
693 *cmds++ = (0x1fff << 16) | (0x1fff);
694 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
695 *cmds++ = PM4_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
696 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
697 *cmds++ = (0x1fff << 16) | (0x1fff);
698
699 /* load the viewport so that z scale = clear depth and
700 * z offset = 0.0f
701 */
702 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
703 *cmds++ = PM4_REG(REG_PA_CL_VPORT_ZSCALE);
704 *cmds++ = 0xbf800000; /* -1.0f */
705 *cmds++ = 0x0;
706
707 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
708 *cmds++ = PM4_REG(REG_RB_COLOR_MASK);
709 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
710
711 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
712 *cmds++ = PM4_REG(REG_RB_COLOR_DEST_MASK);
713 *cmds++ = 0xffffffff;
714
715 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
716 *cmds++ = PM4_REG(REG_SQ_WRAPPING_0);
717 *cmds++ = 0x00000000;
718 *cmds++ = 0x00000000;
719
720 /* load the stencil ref value
721 * $AAM - do this later
722 */
723
724 /* load the COPY state */
725 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 6);
726 *cmds++ = PM4_REG(REG_RB_COPY_CONTROL);
727 *cmds++ = 0; /* RB_COPY_CONTROL */
728 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
729 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
730
731 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
732 * MaskWrite:R=G=B=A=1
733 */
734 *cmds++ = 0x0003c008 |
735 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
736 /* Make sure we stay in offsetx field. */
737 BUG_ON(offset & 0xfffff000);
738 *cmds++ = offset;
739
740 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
741 *cmds++ = PM4_REG(REG_RB_MODECONTROL);
742 *cmds++ = 0x6; /* EDRAM copy */
743
744 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
745 *cmds++ = PM4_REG(REG_PA_CL_CLIP_CNTL);
746 *cmds++ = 0x00010000;
747
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600748 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600749 *cmds++ = pm4_type3_packet(PM4_SET_DRAW_INIT_FLAGS, 1);
750 *cmds++ = 0;
751
752 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
753 *cmds++ = PM4_REG(REG_LEIA_RB_LRZ_VSC_CONTROL);
754 *cmds++ = 0x0000000;
755
756 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 3);
757 *cmds++ = 0; /* viz query info. */
758 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
759 *cmds++ = 0x00004088;
760 *cmds++ = 3; /* NumIndices=3 */
761 } else {
762 /* queue the draw packet */
763 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2);
764 *cmds++ = 0; /* viz query info. */
765 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
766 *cmds++ = 0x00030088;
767 }
768
769 /* create indirect buffer command for above command sequence */
770 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
771
772 return cmds;
773}
774
775/* context restore */
776
777/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
778static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
779 struct adreno_context *drawctxt,
780 struct gmem_shadow_t *shadow)
781{
782 unsigned int *cmds = shadow->gmem_restore_commands;
783 unsigned int *start = cmds;
784
785 /* Store TP0_CHICKEN register */
786 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
787 *cmds++ = REG_TP0_CHICKEN;
788 *cmds++ = tmp_ctx.chicken_restore;
789
790 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
791 *cmds++ = 0;
792
793 /* Set TP0_CHICKEN to zero */
794 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
795 *cmds++ = 0x00000000;
796
797 /* Set PA_SC_AA_CONFIG to 0 */
798 *cmds++ = pm4_type0_packet(REG_PA_SC_AA_CONFIG, 1);
799 *cmds++ = 0x00000000;
800 /* shader constants */
801
802 /* vertex buffer constants */
803 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 7);
804
805 *cmds++ = (0x1 << 16) | (9 * 6);
806 /* valid(?) vtx constant flag & addr */
807 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
808 /* limit = 12 dwords */
809 *cmds++ = 0x00000030;
810 /* valid(?) vtx constant flag & addr */
811 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
812 /* limit = 8 dwords */
813 *cmds++ = 0x00000020;
814 *cmds++ = 0;
815 *cmds++ = 0;
816
817 /* Invalidate L2 cache to make sure vertices are updated */
818 *cmds++ = pm4_type0_packet(REG_TC_CNTL_STATUS, 1);
819 *cmds++ = 0x1;
820
821 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
822
Tarun Karra16346b02011-07-24 15:04:26 -0700823 /* Repartition shaders */
824 *cmds++ = pm4_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
825 *cmds++ = 0x180;
826
827 /* Invalidate Vertex & Pixel instruction code address and sizes */
828 *cmds++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1);
829 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
830
831 *cmds++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1);
832 *cmds++ = (0x80000000) | 0x180;
833
Jordan Crousea78c9172011-07-11 13:14:09 -0600834 /* Load the patched fragment shader stream */
835 cmds =
836 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
837
838 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
839 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
840 *cmds++ = PM4_REG(REG_SQ_PROGRAM_CNTL);
841 *cmds++ = 0x10030002;
842 *cmds++ = 0x00000008;
843
844 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
845 *cmds++ = PM4_REG(REG_PA_SC_AA_MASK);
846 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
847
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600848 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600849 /* PA_SC_VIZ_QUERY */
850 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
851 *cmds++ = PM4_REG(REG_PA_SC_VIZ_QUERY);
852 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
853 }
854
855 /* RB_COLORCONTROL */
856 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
857 *cmds++ = PM4_REG(REG_RB_COLORCONTROL);
858 *cmds++ = 0x00000c20;
859
860 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
861 *cmds++ = PM4_REG(REG_VGT_MAX_VTX_INDX);
862 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
863 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
864 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
865
866 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
867 *cmds++ = PM4_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
868 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
869 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
870
871 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
872 *cmds++ = PM4_REG(REG_SQ_INTERPOLATOR_CNTL);
873 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
874
875 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
876 *cmds++ = PM4_REG(REG_PA_SC_AA_CONFIG);
877 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
878
879 /* set REG_PA_SU_SC_MODE_CNTL
880 * Front_ptype = draw triangles
881 * Back_ptype = draw triangles
882 * Provoking vertex = last
883 */
884 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
885 *cmds++ = PM4_REG(REG_PA_SU_SC_MODE_CNTL);
886 *cmds++ = 0x00080240;
887
888 /* texture constants */
889 *cmds++ =
890 pm4_type3_packet(PM4_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
891 *cmds++ = (0x1 << 16) | (0 * 6);
892 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
893 cmds[0] |= (shadow->pitch >> 5) << 22;
894 cmds[1] |=
895 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
896 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
897 cmds += SYS2GMEM_TEX_CONST_LEN;
898
899 /* program surface info */
900 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
901 *cmds++ = PM4_REG(REG_RB_SURFACE_INFO);
902 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
903
904 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
905 * Base=gmem_base
906 */
907 *cmds++ =
908 (shadow->
909 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
910
911 /* RB_DEPTHCONTROL */
912 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
913 *cmds++ = PM4_REG(REG_RB_DEPTHCONTROL);
914
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600915 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600916 *cmds++ = 8; /* disable Z */
917 else
918 *cmds++ = 0; /* disable Z */
919
920 /* Use maximum scissor values -- quad vertices already
921 * have the correct bounds */
922 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
923 *cmds++ = PM4_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
924 *cmds++ = (0 << 16) | 0;
925 *cmds++ = ((0x1fff) << 16) | 0x1fff;
926 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
927 *cmds++ = PM4_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
928 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
929 *cmds++ = ((0x1fff) << 16) | 0x1fff;
930
931 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
932 *cmds++ = PM4_REG(REG_PA_CL_VTE_CNTL);
933 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
934 *cmds++ = 0x00000b00;
935
936 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
937 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
938 *cmds++ = PM4_REG(REG_PA_CL_VPORT_ZSCALE);
939 *cmds++ = 0xbf800000;
940 *cmds++ = 0x0;
941
942 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
943 *cmds++ = PM4_REG(REG_RB_COLOR_MASK);
944 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
945
946 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
947 *cmds++ = PM4_REG(REG_RB_COLOR_DEST_MASK);
948 *cmds++ = 0xffffffff;
949
950 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
951 *cmds++ = PM4_REG(REG_SQ_WRAPPING_0);
952 *cmds++ = 0x00000000;
953 *cmds++ = 0x00000000;
954
955 /* load the stencil ref value
956 * $AAM - do this later
957 */
958 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
959 *cmds++ = PM4_REG(REG_RB_MODECONTROL);
960 /* draw pixels with color and depth/stencil component */
961 *cmds++ = 0x4;
962
963 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
964 *cmds++ = PM4_REG(REG_PA_CL_CLIP_CNTL);
965 *cmds++ = 0x00010000;
966
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600967 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600968 *cmds++ = pm4_type3_packet(PM4_SET_DRAW_INIT_FLAGS, 1);
969 *cmds++ = 0;
970
971 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
972 *cmds++ = PM4_REG(REG_LEIA_RB_LRZ_VSC_CONTROL);
973 *cmds++ = 0x0000000;
974
975 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 3);
976 *cmds++ = 0; /* viz query info. */
977 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
978 *cmds++ = 0x00004088;
979 *cmds++ = 3; /* NumIndices=3 */
980 } else {
981 /* queue the draw packet */
982 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2);
983 *cmds++ = 0; /* viz query info. */
984 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
985 *cmds++ = 0x00030088;
986 }
987
988 /* create indirect buffer command for above command sequence */
989 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
990
991 return cmds;
992}
993
994/* restore h/w regs, alu constants, texture constants, etc. ... */
995static unsigned *reg_range(unsigned int *cmd, unsigned int start,
996 unsigned int end)
997{
998 *cmd++ = PM4_REG(start); /* h/w regs, start addr */
999 *cmd++ = end - start + 1; /* count */
1000 return cmd;
1001}
1002
1003static void build_regrestore_cmds(struct adreno_device *adreno_dev,
1004 struct adreno_context *drawctxt)
1005{
1006 unsigned int *start = tmp_ctx.cmd;
1007 unsigned int *cmd = start;
1008
1009 unsigned int i = 0;
1010 unsigned int reg_array_size = 0;
1011 const unsigned int *ptr_register_ranges;
1012
1013 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1014 *cmd++ = 0;
1015
1016 /* H/W Registers */
1017 /* deferred pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, ???); */
1018 cmd++;
1019#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1020 /* Force mismatch */
1021 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1022#else
1023 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1024#endif
1025
1026 /* Based on chip id choose the registers ranges*/
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001027 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001028 ptr_register_ranges = register_ranges_a22x;
1029 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
1030 } else {
1031 ptr_register_ranges = register_ranges_a20x;
1032 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1033 }
1034
1035
1036 for (i = 0; i < (reg_array_size/2); i++) {
1037 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1038 ptr_register_ranges[i*2+1]);
1039 }
1040
1041 /* Now we know how many register blocks we have, we can compute command
1042 * length
1043 */
1044 start[2] =
1045 pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
1046 /* Enable shadowing for the entire register block. */
1047#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1048 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1049#else
1050 start[4] |= (1 << 24) | (4 << 16);
1051#endif
1052
1053 /* Need to handle some of the registers separately */
1054 *cmd++ = pm4_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
1055 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1056 *cmd++ = 0x00040400;
1057
1058 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1059 *cmd++ = 0;
1060 *cmd++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
1061 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1062 *cmd++ = 0x00000000;
1063
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001064 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001065 unsigned int i;
1066 unsigned int j = 2;
1067 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
1068 REG_LEIA_VSC_PIPE_DATA_LENGTH_7; i++) {
1069 *cmd++ = pm4_type0_packet(i, 1);
1070 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1071 &drawctxt->gpustate);
1072 *cmd++ = 0x00000000;
1073 j++;
1074 }
1075 }
1076
1077 /* ALU Constants */
1078 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
1079 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1080#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1081 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1082#else
1083 *cmd++ = (1 << 24) | (0 << 16) | 0;
1084#endif
1085 *cmd++ = ALU_CONSTANTS;
1086
1087 /* Texture Constants */
1088 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
1089 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1090#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1091 /* Disable shadowing */
1092 *cmd++ = (0 << 24) | (1 << 16) | 0;
1093#else
1094 *cmd++ = (1 << 24) | (1 << 16) | 0;
1095#endif
1096 *cmd++ = TEX_CONSTANTS;
1097
1098 /* Boolean Constants */
1099 *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + BOOL_CONSTANTS);
1100 *cmd++ = (2 << 16) | 0;
1101
1102 /* the next BOOL_CONSTANT dwords is the shadow area for
1103 * boolean constants.
1104 */
1105 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1106 cmd += BOOL_CONSTANTS;
1107
1108 /* Loop Constants */
1109 *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + LOOP_CONSTANTS);
1110 *cmd++ = (3 << 16) | 0;
1111
1112 /* the next LOOP_CONSTANTS dwords is the shadow area for
1113 * loop constants.
1114 */
1115 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1116 cmd += LOOP_CONSTANTS;
1117
1118 /* create indirect buffer command for above command sequence */
1119 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1120
1121 tmp_ctx.cmd = cmd;
1122}
1123
1124/* quad for saving/restoring gmem */
1125static void set_gmem_copy_quad(struct gmem_shadow_t *shadow)
1126{
1127 /* set vertex buffer values */
1128 gmem_copy_quad[1] = uint2float(shadow->height);
1129 gmem_copy_quad[3] = uint2float(shadow->width);
1130 gmem_copy_quad[4] = uint2float(shadow->height);
1131 gmem_copy_quad[9] = uint2float(shadow->width);
1132
1133 gmem_copy_quad[0] = uint2float(0);
1134 gmem_copy_quad[6] = uint2float(0);
1135 gmem_copy_quad[7] = uint2float(0);
1136 gmem_copy_quad[10] = uint2float(0);
1137
1138 memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
1139
1140 memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
1141 TEXCOORD_LEN << 2);
1142}
1143
1144/* quad for saving/restoring gmem */
1145static void build_quad_vtxbuff(struct adreno_context *drawctxt,
1146 struct gmem_shadow_t *shadow)
1147{
1148 unsigned int *cmd = tmp_ctx.cmd;
1149
1150 /* quad vertex buffer location (in GPU space) */
1151 shadow->quad_vertices.hostptr = cmd;
1152 shadow->quad_vertices.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
1153
1154 cmd += QUAD_LEN;
1155
1156 /* tex coord buffer location (in GPU space) */
1157 shadow->quad_texcoords.hostptr = cmd;
1158 shadow->quad_texcoords.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
1159
1160 cmd += TEXCOORD_LEN;
1161
1162 set_gmem_copy_quad(shadow);
1163
1164 tmp_ctx.cmd = cmd;
1165}
1166
1167static void
1168build_shader_save_restore_cmds(struct adreno_context *drawctxt)
1169{
1170 unsigned int *cmd = tmp_ctx.cmd;
1171 unsigned int *save, *restore, *fixup;
1172#if defined(PM4_IM_STORE)
1173 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
1174#endif
1175 unsigned int *partition1;
1176 unsigned int *shaderBases, *partition2;
1177
1178#if defined(PM4_IM_STORE)
1179 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1180 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
1181 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex + SHADER_SHADOW_SIZE;
1182 tmp_ctx.shader_shared = tmp_ctx.shader_pixel + SHADER_SHADOW_SIZE;
1183#endif
1184
1185 /* restore shader partitioning and instructions */
1186
1187 restore = cmd; /* start address */
1188
1189 /* Invalidate Vertex & Pixel instruction code address and sizes */
1190 *cmd++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1);
1191 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1192
1193 /* Restore previous shader vertex & pixel instruction bases. */
1194 *cmd++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1);
1195 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1196
1197 /* write the shader partition information to a scratch register */
1198 *cmd++ = pm4_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
1199 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1200
1201#if defined(PM4_IM_STORE)
1202 /* load vertex shader instructions from the shadow. */
1203 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1204 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1205 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1206
1207 /* load pixel shader instructions from the shadow. */
1208 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1209 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1210 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1211
1212 /* load shared shader instructions from the shadow. */
1213 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1214 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1215 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
1216#endif
1217
1218 /* create indirect buffer command for above command sequence */
1219 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1220
1221 /*
1222 * fixup SET_SHADER_BASES data
1223 *
1224 * since self-modifying PM4 code is being used here, a seperate
1225 * command buffer is used for this fixup operation, to ensure the
1226 * commands are not read by the PM4 engine before the data fields
1227 * have been written.
1228 */
1229
1230 fixup = cmd; /* start address */
1231
1232 /* write the shader partition information to a scratch register */
1233 *cmd++ = pm4_type0_packet(REG_SCRATCH_REG2, 1);
1234 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1235
1236 /* mask off unused bits, then OR with shader instruction memory size */
1237 *cmd++ = pm4_type3_packet(PM4_REG_RMW, 3);
1238 *cmd++ = REG_SCRATCH_REG2;
1239 /* AND off invalid bits. */
1240 *cmd++ = 0x0FFF0FFF;
1241 /* OR in instruction memory size */
1242 *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2 - 5U) << 29);
1243
1244 /* write the computed value to the SET_SHADER_BASES data field */
1245 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1246 *cmd++ = REG_SCRATCH_REG2;
1247 /* TBD #5: shader bases (to restore) */
1248 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1249
1250 /* create indirect buffer command for above command sequence */
1251 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1252
1253 /* save shader partitioning and instructions */
1254
1255 save = cmd; /* start address */
1256
1257 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1258 *cmd++ = 0;
1259
1260 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1261 * store the value in the data fields of the SET_CONSTANT commands
1262 * above.
1263 */
1264 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1265 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1266 /* TBD #4a: partition info (to restore) */
1267 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
1268 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1269 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1270 /* TBD #4b: partition info (to fixup) */
1271 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1272
1273#if defined(PM4_IM_STORE)
1274
1275 /* store the vertex shader instructions */
1276 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1277 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1278 /* TBD #1: start/size (to restore) */
1279 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1280
1281 /* store the pixel shader instructions */
1282 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1283 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1284 /* TBD #2: start/size (to restore) */
1285 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1286
1287 /* store the shared shader instructions if vertex base is nonzero */
1288
1289 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1290 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1291 /* TBD #3: start/size (to restore) */
1292 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1293
1294#endif
1295
1296 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1297 *cmd++ = 0;
1298
1299 /* create indirect buffer command for above command sequence */
1300 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1301
1302 tmp_ctx.cmd = cmd;
1303}
1304
1305/* create buffers for saving/restoring registers, constants, & GMEM */
1306static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1307 struct adreno_context *drawctxt)
1308{
1309 int result;
1310
1311 /* Allocate vmalloc memory to store the gpustate */
1312 result = kgsl_allocate(&drawctxt->gpustate,
1313 drawctxt->pagetable, CONTEXT_SIZE);
1314
1315 if (result)
1316 return result;
1317
1318 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1319
1320 /* Blank out h/w register, constant, and command buffer shadows. */
1321 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
1322
1323 /* set-up command and vertex buffer pointers */
1324 tmp_ctx.cmd = tmp_ctx.start
1325 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1326
1327 /* build indirect command buffers to save & restore regs/constants */
1328 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1329 build_regrestore_cmds(adreno_dev, drawctxt);
1330 build_regsave_cmds(adreno_dev, drawctxt);
1331
1332 build_shader_save_restore_cmds(drawctxt);
1333
1334 kgsl_cache_range_op(&drawctxt->gpustate,
1335 KGSL_CACHE_OP_FLUSH);
1336
1337 return 0;
1338}
1339
1340/* create buffers for saving/restoring registers, constants, & GMEM */
1341static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1342 struct adreno_context *drawctxt)
1343{
1344 int result;
1345
1346 config_gmemsize(&drawctxt->context_gmem_shadow,
1347 adreno_dev->gmemspace.sizebytes);
1348 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1349
1350 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1351 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1352
1353 if (result)
1354 return result;
1355
1356 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1357 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1358
1359 /* blank out gmem shadow. */
1360 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1361 drawctxt->context_gmem_shadow.size);
1362
1363 /* build quad vertex buffer */
1364 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow);
1365
1366 /* build TP0_CHICKEN register restore command buffer */
1367 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1368
1369 /* build indirect command buffers to save & restore gmem */
1370 /* Idle because we are reading PM override registers */
1371 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1372 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1373 tmp_ctx.cmd =
1374 build_gmem2sys_cmds(adreno_dev, drawctxt,
1375 &drawctxt->context_gmem_shadow);
1376 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1377 tmp_ctx.cmd =
1378 build_sys2gmem_cmds(adreno_dev, drawctxt,
1379 &drawctxt->context_gmem_shadow);
1380
1381 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1382 KGSL_CACHE_OP_FLUSH);
1383
1384 return 0;
1385}
1386
1387static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1388 struct adreno_context *context)
1389{
1390 struct kgsl_device *device = &adreno_dev->dev;
1391
1392 if (context == NULL)
1393 return;
1394
1395 if (context->flags & CTXT_FLAGS_GPU_HANG)
1396 KGSL_CTXT_WARN(device,
1397 "Current active context has caused gpu hang\n");
1398
1399 KGSL_CTXT_INFO(device,
1400 "active context flags %08x\n", context->flags);
1401
1402 /* save registers and constants. */
1403 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1404
1405 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1406 /* save shader partitioning and instructions. */
1407 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1408 context->shader_save, 3);
1409
1410 /* fixup shader partitioning parameter for
1411 * SET_SHADER_BASES.
1412 */
1413 adreno_ringbuffer_issuecmds(device, 0,
1414 context->shader_fixup, 3);
1415
1416 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1417 }
1418
1419 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1420 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1421 /* save gmem.
1422 * (note: changes shader. shader must already be saved.)
1423 */
1424 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1425 context->context_gmem_shadow.gmem_save, 3);
1426
1427 /* Restore TP0_CHICKEN */
1428 adreno_ringbuffer_issuecmds(device, 0,
1429 context->chicken_restore, 3);
1430
1431 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
1432 }
1433}
1434
1435static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1436 struct adreno_context *context)
1437{
1438 struct kgsl_device *device = &adreno_dev->dev;
1439 unsigned int cmds[5];
1440
1441 if (context == NULL) {
1442 /* No context - set the default apgetable and thats it */
1443 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1444 return;
1445 }
1446
1447 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1448
1449 cmds[0] = pm4_nop_packet(1);
1450 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
1451 cmds[2] = pm4_type3_packet(PM4_MEM_WRITE, 2);
1452 cmds[3] = device->memstore.gpuaddr +
1453 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1454 cmds[4] = (unsigned int) context;
1455 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1456 kgsl_mmu_setstate(device, context->pagetable);
1457
1458#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1459 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1460 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1461 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1462#endif
1463
1464 /* restore gmem.
1465 * (note: changes shader. shader must not already be restored.)
1466 */
1467 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1468 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1469 context->context_gmem_shadow.gmem_restore, 3);
1470
1471 /* Restore TP0_CHICKEN */
1472 adreno_ringbuffer_issuecmds(device, 0,
1473 context->chicken_restore, 3);
1474
1475 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1476 }
1477
1478 /* restore registers and constants. */
1479 adreno_ringbuffer_issuecmds(device, 0,
1480 context->reg_restore, 3);
1481
1482 /* restore shader instructions & partitioning. */
1483 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1484 adreno_ringbuffer_issuecmds(device, 0,
1485 context->shader_restore, 3);
1486 }
1487
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001488 if (adreno_is_a20x(adreno_dev)) {
1489 cmds[0] = pm4_type3_packet(PM4_SET_BIN_BASE_OFFSET, 1);
1490 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001491 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001492 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001493}
1494
1495/*
1496 * Interrupt management
1497 *
1498 * a2xx interrupt control is distributed among the various
1499 * hardware components (RB, CP, MMU). The main interrupt
1500 * tells us which component fired the interrupt, but one needs
1501 * to go to the individual component to find out why. The
1502 * following functions provide the broken out support for
1503 * managing the interrupts
1504 */
1505
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001506#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001507
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001508#define CP_INT_MASK \
1509 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001510 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1511 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1512 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1513 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001514 CP_INT_CNTL__IB1_INT_MASK | \
1515 CP_INT_CNTL__RB_INT_MASK)
1516
1517#define VALID_STATUS_COUNT_MAX 10
1518
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001519static struct {
1520 unsigned int mask;
1521 const char *message;
1522} kgsl_cp_error_irqs[] = {
1523 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1524 "ringbuffer TO packet in IB interrupt" },
1525 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1526 "ringbuffer opcode error interrupt" },
1527 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1528 "ringbuffer protected mode error interrupt" },
1529 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1530 "ringbuffer reserved bit error interrupt" },
1531 { CP_INT_CNTL__IB_ERROR_MASK,
1532 "ringbuffer IB error interrupt" },
1533};
1534
Jordan Crousea78c9172011-07-11 13:14:09 -06001535static void a2xx_cp_intrcallback(struct kgsl_device *device)
1536{
1537 unsigned int status = 0, num_reads = 0, master_status = 0;
1538 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1539 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001540 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001541
1542 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1543 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1544 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1545 adreno_regread(device, REG_CP_INT_STATUS, &status);
1546 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1547 &master_status);
1548 num_reads++;
1549 }
1550 if (num_reads > 1)
1551 KGSL_DRV_WARN(device,
1552 "Looped %d times to read REG_CP_INT_STATUS\n",
1553 num_reads);
1554 if (!status) {
1555 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1556 /* This indicates that we could not read CP_INT_STAT.
1557 * As a precaution just wake up processes so
1558 * they can check their timestamps. Since, we
1559 * did not ack any interrupts this interrupt will
1560 * be generated again */
1561 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1562 wake_up_interruptible_all(&device->wait_queue);
1563 } else
1564 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1565 return;
1566 }
1567
1568 if (status & CP_INT_CNTL__RB_INT_MASK) {
1569 /* signal intr completion event */
1570 unsigned int enableflag = 0;
1571 kgsl_sharedmem_writel(&rb->device->memstore,
1572 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1573 enableflag);
1574 wmb();
1575 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1576 }
1577
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001578 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1579 if (status & kgsl_cp_error_irqs[i].mask) {
1580 KGSL_CMD_CRIT(rb->device, "%s\n",
1581 kgsl_cp_error_irqs[i].message);
1582 /*
1583 * on fatal errors, turn off the interrupts to
1584 * avoid storming. This has the side effect of
1585 * forcing a PM dump when the timestamp times out
1586 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001587
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001588 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1589 }
1590 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001591
1592 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001593 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001594 adreno_regwrite(device, REG_CP_INT_ACK, status);
1595
1596 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1597 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
1598 wake_up_interruptible_all(&device->wait_queue);
1599 atomic_notifier_call_chain(&(device->ts_notifier_list),
1600 device->id,
1601 NULL);
1602 }
1603}
1604
1605static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1606{
1607 unsigned int status = 0;
1608 unsigned int rderr = 0;
1609
1610 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1611
1612 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1613 union rbbm_read_error_u rerr;
1614 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1615 rerr.val = rderr;
1616 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1617 rerr.f.read_error &&
1618 rerr.f.read_requester)
1619 KGSL_DRV_WARN(device,
1620 "rbbm read error interrupt: %08x\n", rderr);
1621 else
1622 KGSL_DRV_CRIT(device,
1623 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001624 }
1625
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001626 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001627 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1628}
1629
1630irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1631{
1632 struct kgsl_device *device = &adreno_dev->dev;
1633 irqreturn_t result = IRQ_NONE;
1634 unsigned int status;
1635
1636 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1637
1638 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1639 kgsl_mh_intrcallback(device);
1640 result = IRQ_HANDLED;
1641 }
1642
1643 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1644 a2xx_cp_intrcallback(device);
1645 result = IRQ_HANDLED;
1646 }
1647
1648 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1649 a2xx_rbbm_intrcallback(device);
1650 result = IRQ_HANDLED;
1651 }
1652
1653 return result;
1654}
1655
1656static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1657{
1658 struct kgsl_device *device = &adreno_dev->dev;
1659
1660 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001661 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1662 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001663 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1664 } else {
1665 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1666 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1667 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1668 }
1669}
1670
1671struct adreno_gpudev adreno_a2xx_gpudev = {
1672 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1673 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1674 .ctxt_save = a2xx_ctxt_save,
1675 .ctxt_restore = a2xx_ctxt_restore,
1676 .irq_handler = a2xx_irq_handler,
1677 .irq_control = a2xx_irq_control,
1678};