blob: 3ca97b51a3aaefa65d26137d9412b9fb3e1a53a7 [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
Jordan Crousea78c9172011-07-11 13:14:09 -060077/* 96-bit instructions */
78#define SHADER_INSTRUCT (1<<SHADER_INSTRUCT_LOG2)
Jordan Crousea78c9172011-07-11 13:14:09 -060079
80/* LOAD_CONSTANT_CONTEXT shadow size */
81#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
82
83#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
84#define REG_SHADOW_SIZE 0x1000 /* 4KB */
85#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
86#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
87#else
88#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
89#endif
90#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
91#define SHADER_SHADOW_SIZE (SHADER_INSTRUCT*12) /* 6KB */
92
93#define REG_OFFSET LCC_SHADOW_SIZE
94#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
95#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
96#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
97
98#define CONTEXT_SIZE (SHADER_OFFSET + 3 * SHADER_SHADOW_SIZE)
99
100/* A scratchpad used to build commands during context create */
101
102static struct tmp_ctx {
103 unsigned int *start; /* Command & Vertex buffer start */
104 unsigned int *cmd; /* Next available dword in C&V buffer */
105
106 /* address of buffers, needed when creating IB1 command buffers. */
107 uint32_t bool_shadow; /* bool constants */
108 uint32_t loop_shadow; /* loop constants */
109
Jordan Crousea78c9172011-07-11 13:14:09 -0600110 uint32_t shader_shared; /* shared shader instruction shadow */
111 uint32_t shader_vertex; /* vertex shader instruction shadow */
112 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600113
114 /* Addresses in command buffer where separately handled registers
115 * are saved
116 */
117 uint32_t reg_values[33];
118 uint32_t chicken_restore;
119
120 uint32_t gmem_base; /* Base gpu address of GMEM */
121
122} tmp_ctx;
123
124/* context save (gmem -> sys) */
125
126/* pre-compiled vertex shader program
127*
128* attribute vec4 P;
129* void main(void)
130* {
131* gl_Position = P;
132* }
133*/
134#define GMEM2SYS_VTX_PGM_LEN 0x12
135
136static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
137 0x00011003, 0x00001000, 0xc2000000,
138 0x00001004, 0x00001000, 0xc4000000,
139 0x00001005, 0x00002000, 0x00000000,
140 0x1cb81000, 0x00398a88, 0x00000003,
141 0x140f803e, 0x00000000, 0xe2010100,
142 0x14000000, 0x00000000, 0xe2000000
143};
144
145/* pre-compiled fragment shader program
146*
147* precision highp float;
148* uniform vec4 clear_color;
149* void main(void)
150* {
151* gl_FragColor = clear_color;
152* }
153*/
154
155#define GMEM2SYS_FRAG_PGM_LEN 0x0c
156
157static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
158 0x00000000, 0x1002c400, 0x10000000,
159 0x00001003, 0x00002000, 0x00000000,
160 0x140f8000, 0x00000000, 0x22000000,
161 0x14000000, 0x00000000, 0xe2000000
162};
163
164/* context restore (sys -> gmem) */
165/* pre-compiled vertex shader program
166*
167* attribute vec4 position;
168* attribute vec4 texcoord;
169* varying vec4 texcoord0;
170* void main()
171* {
172* gl_Position = position;
173* texcoord0 = texcoord;
174* }
175*/
176
177#define SYS2GMEM_VTX_PGM_LEN 0x18
178
179static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
180 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
181 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
182 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
183 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
184 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
185 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
186};
187
188/* pre-compiled fragment shader program
189*
190* precision mediump float;
191* uniform sampler2D tex0;
192* varying vec4 texcoord0;
193* void main()
194* {
195* gl_FragColor = texture2D(tex0, texcoord0.xy);
196* }
197*/
198
199#define SYS2GMEM_FRAG_PGM_LEN 0x0f
200
201static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
202 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
203 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
204 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
205 0x14000000, 0x00000000, 0xe2000000
206};
207
208/* shader texture constants (sysmem -> gmem) */
209#define SYS2GMEM_TEX_CONST_LEN 6
210
211static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
212 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
213 * RFMode=ZeroClamp-1, Dim=1:2d
214 */
215 0x00000002, /* Pitch = TBD */
216
217 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
218 * NearestClamp=1:OGL Mode
219 */
220 0x00000800, /* Address[31:12] = TBD */
221
222 /* Width, Height, EndianSwap=0:None */
223 0, /* Width & Height = TBD */
224
225 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
226 * Mip=2:BaseMap
227 */
228 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
229
230 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
231 * Dim3d=0
232 */
233 0,
234
235 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
236 * Dim=1:2d, MipPacking=0
237 */
238 1 << 9 /* Mip Address[31:12] = TBD */
239};
240
Jordan Crousea78c9172011-07-11 13:14:09 -0600241#define NUM_COLOR_FORMATS 13
242
243static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
244 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
245 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
246 FMT_5_6_5, /* COLORX_5_6_5 */
247 FMT_8, /* COLORX_8 */
248 FMT_8_8, /* COLORX_8_8 */
249 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
250 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
251 FMT_16_FLOAT, /* COLORX_16_FLOAT */
252 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
253 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
254 FMT_32_FLOAT, /* COLORX_32_FLOAT */
255 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
256 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
257};
258
259static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
260 2, /* COLORX_4_4_4_4 */
261 2, /* COLORX_1_5_5_5 */
262 2, /* COLORX_5_6_5 */
263 1, /* COLORX_8 */
264 2, /* COLORX_8_8 8*/
265 4, /* COLORX_8_8_8_8 */
266 4, /* COLORX_S8_8_8_8 */
267 2, /* COLORX_16_FLOAT */
268 4, /* COLORX_16_16_FLOAT */
269 8, /* COLORX_16_16_16_16_FLOAT */
270 4, /* COLORX_32_FLOAT */
271 8, /* COLORX_32_32_FLOAT */
272 16, /* COLORX_32_32_32_32_FLOAT */
273};
274
275/* shader linkage info */
276#define SHADER_CONST_ADDR (11 * 6 + 3)
277
Jordan Crousea78c9172011-07-11 13:14:09 -0600278
279static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
280 unsigned int *shader_pgm, int dwords)
281{
282 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600283 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600284 /* 0=vertex shader, 1=fragment shader */
285 *cmds++ = vtxfrag;
286 /* instruction start & size (in 32-bit words) */
287 *cmds++ = ((0 << 16) | dwords);
288
289 memcpy(cmds, shader_pgm, dwords << 2);
290 cmds += dwords;
291
292 return cmds;
293}
294
295static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
296 uint32_t src, int dwords)
297{
298 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600299 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600300 *cmds++ = src++;
301 *cmds++ = dst;
302 dst += 4;
303 }
304
305 return cmds;
306}
307
308#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
309
310static void build_reg_to_mem_range(unsigned int start, unsigned int end,
311 unsigned int **cmd,
312 struct adreno_context *drawctxt)
313{
314 unsigned int i = start;
315
316 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600317 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600318 *(*cmd)++ = i;
319 *(*cmd)++ =
320 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
321 (i - 0x2000) * 4;
322 }
323}
324
325#endif
326
327/* chicken restore */
328static unsigned int *build_chicken_restore_cmds(
329 struct adreno_context *drawctxt)
330{
331 unsigned int *start = tmp_ctx.cmd;
332 unsigned int *cmds = start;
333
Jordan Crouse084427d2011-07-28 08:37:58 -0600334 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600335 *cmds++ = 0;
336
Jordan Crouse084427d2011-07-28 08:37:58 -0600337 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600338 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
339 *cmds++ = 0x00000000;
340
341 /* create indirect buffer command for above command sequence */
342 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
343
344 return cmds;
345}
346
347/****************************************************************************/
348/* context save */
349/****************************************************************************/
350
351static const unsigned int register_ranges_a20x[] = {
352 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
353 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
354 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
355 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
356 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
357 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
358 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
359 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
360 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
361 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
362 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
363 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
364 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
365 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
366};
367
368static const unsigned int register_ranges_a22x[] = {
369 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
370 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
371 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
372 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
373 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
374 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
375 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
376 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
377 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700378 /* all the below registers are specific to a220 */
379 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600380 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
381 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
382 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
383 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
384 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700385 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
386 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600387 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
388};
389
390
391/* save h/w regs, alu constants, texture contants, etc. ...
392* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
393*/
394static void build_regsave_cmds(struct adreno_device *adreno_dev,
395 struct adreno_context *drawctxt)
396{
397 unsigned int *start = tmp_ctx.cmd;
398 unsigned int *cmd = start;
399
Jordan Crouse084427d2011-07-28 08:37:58 -0600400 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600401 *cmd++ = 0;
402
403#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
404 /* Make sure the HW context has the correct register values
405 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600406 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600407 *cmd++ = 0;
408
409 {
410 unsigned int i = 0;
411 unsigned int reg_array_size = 0;
412 const unsigned int *ptr_register_ranges;
413
414 /* Based on chip id choose the register ranges */
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600415 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600416 ptr_register_ranges = register_ranges_a22x;
417 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
418 } else {
419 ptr_register_ranges = register_ranges_a20x;
420 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
421 }
422
423
424 /* Write HW registers into shadow */
425 for (i = 0; i < (reg_array_size/2) ; i++) {
426 build_reg_to_mem_range(ptr_register_ranges[i*2],
427 ptr_register_ranges[i*2+1],
428 &cmd, drawctxt);
429 }
430 }
431
432 /* Copy ALU constants */
433 cmd =
434 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
435 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
436
437 /* Copy Tex constants */
438 cmd =
439 reg_to_mem(cmd,
440 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
441 REG_SQ_FETCH_0, TEX_CONSTANTS);
442#else
443
444 /* Insert a wait for idle packet before reading the registers.
445 * This is to fix a hang/reset seen during stress testing. In this
446 * hang, CP encountered a timeout reading SQ's boolean constant
447 * register. There is logic in the HW that blocks reading of this
448 * register when the SQ block is not idle, which we believe is
449 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600450 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600451 *cmd++ = 0;
452
453 /* H/w registers are already shadowed; just need to disable shadowing
454 * to prevent corruption.
455 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600456 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600457 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
458 *cmd++ = 4 << 16; /* regs, start=0 */
459 *cmd++ = 0x0; /* count = 0 */
460
461 /* ALU constants are already shadowed; just need to disable shadowing
462 * to prevent corruption.
463 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600464 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600465 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
466 *cmd++ = 0 << 16; /* ALU, start=0 */
467 *cmd++ = 0x0; /* count = 0 */
468
469 /* Tex constants are already shadowed; just need to disable shadowing
470 * to prevent corruption.
471 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600472 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600473 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
474 *cmd++ = 1 << 16; /* Tex, start=0 */
475 *cmd++ = 0x0; /* count = 0 */
476#endif
477
478 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600479 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600480 *cmd++ = REG_SQ_GPR_MANAGEMENT;
481 *cmd++ = tmp_ctx.reg_values[0];
482
Jordan Crouse084427d2011-07-28 08:37:58 -0600483 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600484 *cmd++ = REG_TP0_CHICKEN;
485 *cmd++ = tmp_ctx.reg_values[1];
486
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600487 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600488 unsigned int i;
489 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700490 for (i = REG_A220_VSC_BIN_SIZE; i <=
491 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600492 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600493 *cmd++ = i;
494 *cmd++ = tmp_ctx.reg_values[j];
495 j++;
496 }
497 }
498
499 /* Copy Boolean constants */
500 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
501 BOOL_CONSTANTS);
502
503 /* Copy Loop constants */
504 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
505 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
506
507 /* create indirect buffer command for above command sequence */
508 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
509
510 tmp_ctx.cmd = cmd;
511}
512
513/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
514static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
515 struct adreno_context *drawctxt,
516 struct gmem_shadow_t *shadow)
517{
518 unsigned int *cmds = shadow->gmem_save_commands;
519 unsigned int *start = cmds;
520 /* Calculate the new offset based on the adjusted base */
521 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
522 unsigned int addr = shadow->gmemshadow.gpuaddr;
523 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
524
525 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600526 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600527 *cmds++ = REG_TP0_CHICKEN;
528
529 *cmds++ = tmp_ctx.chicken_restore;
530
Jordan Crouse084427d2011-07-28 08:37:58 -0600531 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600532 *cmds++ = 0;
533
534 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600535 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600536 *cmds++ = 0x00000000;
537
538 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600539 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600540 *cmds++ = 0x00000000;
541
542 /* program shader */
543
544 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600545 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600546 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
547 *cmds++ = 0;
548 /* valid(?) vtx constant flag & addr */
549 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
550 /* limit = 12 dwords */
551 *cmds++ = 0x00000030;
552
553 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600554 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600555 *cmds++ = 0x1;
556
Jordan Crouse084427d2011-07-28 08:37:58 -0600557 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600558 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600559 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
560 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
561 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
562
Jordan Crouse084427d2011-07-28 08:37:58 -0600563 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600564 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600565 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
566
Jordan Crouse084427d2011-07-28 08:37:58 -0600567 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600568 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600569 *cmds++ = 0x00000c20;
570
Tarun Karra16346b02011-07-24 15:04:26 -0700571 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600572 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700573 *cmds++ = 0x180;
574
575 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600576 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700577 *cmds++ = 0x00003F00;
578
Jordan Crouse084427d2011-07-28 08:37:58 -0600579 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700580 *cmds++ = (0x80000000) | 0x180;
581
Jordan Crousea78c9172011-07-11 13:14:09 -0600582 /* load the patched vertex shader stream */
583 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
584
585 /* Load the patched fragment shader stream */
586 cmds =
587 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
588
589 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600590 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600591 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600592 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600593 *cmds++ = 0x10018001;
594 else
595 *cmds++ = 0x10010001;
596 *cmds++ = 0x00000008;
597
598 /* resolve */
599
600 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600601 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600602 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600603 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
604 *cmds++ = 0x00000b00;
605
606 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600607 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600608 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600609 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
610
611 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
612 * Base=gmem_base
613 */
614 /* gmem base assumed 4K aligned. */
615 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
616 *cmds++ =
617 (shadow->
618 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
619
620 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600621 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600622 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600623 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600624 *cmds++ = 0x08;
625 else
626 *cmds++ = 0;
627
628 /* set REG_PA_SU_SC_MODE_CNTL
629 * Front_ptype = draw triangles
630 * Back_ptype = draw triangles
631 * Provoking vertex = last
632 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600633 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600634 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600635 *cmds++ = 0x00080240;
636
637 /* Use maximum scissor values -- quad vertices already have the
638 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600639 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600640 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600641 *cmds++ = (0 << 16) | 0;
642 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600643 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600644 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600645 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
646 *cmds++ = (0x1fff << 16) | (0x1fff);
647
648 /* load the viewport so that z scale = clear depth and
649 * z offset = 0.0f
650 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600651 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600652 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600653 *cmds++ = 0xbf800000; /* -1.0f */
654 *cmds++ = 0x0;
655
Jordan Crouse084427d2011-07-28 08:37:58 -0600656 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600657 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600658 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
659
Jordan Crouse084427d2011-07-28 08:37:58 -0600660 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600661 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600662 *cmds++ = 0xffffffff;
663
Jordan Crouse084427d2011-07-28 08:37:58 -0600664 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600665 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600666 *cmds++ = 0x00000000;
667 *cmds++ = 0x00000000;
668
669 /* load the stencil ref value
670 * $AAM - do this later
671 */
672
673 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600674 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600675 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600676 *cmds++ = 0; /* RB_COPY_CONTROL */
677 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
678 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
679
680 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
681 * MaskWrite:R=G=B=A=1
682 */
683 *cmds++ = 0x0003c008 |
684 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
685 /* Make sure we stay in offsetx field. */
686 BUG_ON(offset & 0xfffff000);
687 *cmds++ = offset;
688
Jordan Crouse084427d2011-07-28 08:37:58 -0600689 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600690 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600691 *cmds++ = 0x6; /* EDRAM copy */
692
Jordan Crouse084427d2011-07-28 08:37:58 -0600693 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600694 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600695 *cmds++ = 0x00010000;
696
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600697 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600698 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600699 *cmds++ = 0;
700
Jordan Crouse084427d2011-07-28 08:37:58 -0600701 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700702 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600703 *cmds++ = 0x0000000;
704
Jordan Crouse084427d2011-07-28 08:37:58 -0600705 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600706 *cmds++ = 0; /* viz query info. */
707 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
708 *cmds++ = 0x00004088;
709 *cmds++ = 3; /* NumIndices=3 */
710 } else {
711 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600712 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600713 *cmds++ = 0; /* viz query info. */
714 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
715 *cmds++ = 0x00030088;
716 }
717
718 /* create indirect buffer command for above command sequence */
719 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
720
721 return cmds;
722}
723
724/* context restore */
725
726/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
727static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
728 struct adreno_context *drawctxt,
729 struct gmem_shadow_t *shadow)
730{
731 unsigned int *cmds = shadow->gmem_restore_commands;
732 unsigned int *start = cmds;
733
734 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600735 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600736 *cmds++ = REG_TP0_CHICKEN;
737 *cmds++ = tmp_ctx.chicken_restore;
738
Jordan Crouse084427d2011-07-28 08:37:58 -0600739 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600740 *cmds++ = 0;
741
742 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600743 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600744 *cmds++ = 0x00000000;
745
746 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600747 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600748 *cmds++ = 0x00000000;
749 /* shader constants */
750
751 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600752 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600753
754 *cmds++ = (0x1 << 16) | (9 * 6);
755 /* valid(?) vtx constant flag & addr */
756 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
757 /* limit = 12 dwords */
758 *cmds++ = 0x00000030;
759 /* valid(?) vtx constant flag & addr */
760 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
761 /* limit = 8 dwords */
762 *cmds++ = 0x00000020;
763 *cmds++ = 0;
764 *cmds++ = 0;
765
766 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600767 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600768 *cmds++ = 0x1;
769
770 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
771
Tarun Karra16346b02011-07-24 15:04:26 -0700772 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600773 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700774 *cmds++ = 0x180;
775
776 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600777 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700778 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
779
Jordan Crouse084427d2011-07-28 08:37:58 -0600780 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700781 *cmds++ = (0x80000000) | 0x180;
782
Jordan Crousea78c9172011-07-11 13:14:09 -0600783 /* Load the patched fragment shader stream */
784 cmds =
785 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
786
787 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600788 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600789 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600790 *cmds++ = 0x10030002;
791 *cmds++ = 0x00000008;
792
Jordan Crouse084427d2011-07-28 08:37:58 -0600793 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600794 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600795 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
796
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600797 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600798 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600799 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600800 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600801 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
802 }
803
804 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600805 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600806 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600807 *cmds++ = 0x00000c20;
808
Jordan Crouse084427d2011-07-28 08:37:58 -0600809 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600810 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600811 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
812 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
813 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
814
Jordan Crouse084427d2011-07-28 08:37:58 -0600815 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600816 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600817 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
818 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
819
Jordan Crouse084427d2011-07-28 08:37:58 -0600820 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600821 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600822 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
823
Jordan Crouse084427d2011-07-28 08:37:58 -0600824 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600825 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600826 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
827
828 /* set REG_PA_SU_SC_MODE_CNTL
829 * Front_ptype = draw triangles
830 * Back_ptype = draw triangles
831 * Provoking vertex = last
832 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600833 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600834 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600835 *cmds++ = 0x00080240;
836
837 /* texture constants */
838 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600839 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600840 *cmds++ = (0x1 << 16) | (0 * 6);
841 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
842 cmds[0] |= (shadow->pitch >> 5) << 22;
843 cmds[1] |=
844 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
845 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
846 cmds += SYS2GMEM_TEX_CONST_LEN;
847
848 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600849 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600850 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600851 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
852
853 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
854 * Base=gmem_base
855 */
856 *cmds++ =
857 (shadow->
858 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
859
860 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600861 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600862 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600863
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600864 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600865 *cmds++ = 8; /* disable Z */
866 else
867 *cmds++ = 0; /* disable Z */
868
869 /* Use maximum scissor values -- quad vertices already
870 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600871 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600872 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600873 *cmds++ = (0 << 16) | 0;
874 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600875 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600876 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600877 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
878 *cmds++ = ((0x1fff) << 16) | 0x1fff;
879
Jordan Crouse084427d2011-07-28 08:37:58 -0600880 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600881 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600882 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
883 *cmds++ = 0x00000b00;
884
885 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600886 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600887 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600888 *cmds++ = 0xbf800000;
889 *cmds++ = 0x0;
890
Jordan Crouse084427d2011-07-28 08:37:58 -0600891 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600892 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600893 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
894
Jordan Crouse084427d2011-07-28 08:37:58 -0600895 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600896 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600897 *cmds++ = 0xffffffff;
898
Jordan Crouse084427d2011-07-28 08:37:58 -0600899 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600900 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600901 *cmds++ = 0x00000000;
902 *cmds++ = 0x00000000;
903
904 /* load the stencil ref value
905 * $AAM - do this later
906 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600907 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600908 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600909 /* draw pixels with color and depth/stencil component */
910 *cmds++ = 0x4;
911
Jordan Crouse084427d2011-07-28 08:37:58 -0600912 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600913 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600914 *cmds++ = 0x00010000;
915
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600916 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600917 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600918 *cmds++ = 0;
919
Jordan Crouse084427d2011-07-28 08:37:58 -0600920 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700921 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600922 *cmds++ = 0x0000000;
923
Jordan Crouse084427d2011-07-28 08:37:58 -0600924 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600925 *cmds++ = 0; /* viz query info. */
926 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
927 *cmds++ = 0x00004088;
928 *cmds++ = 3; /* NumIndices=3 */
929 } else {
930 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600931 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600932 *cmds++ = 0; /* viz query info. */
933 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
934 *cmds++ = 0x00030088;
935 }
936
937 /* create indirect buffer command for above command sequence */
938 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
939
940 return cmds;
941}
942
Jordan Crousea78c9172011-07-11 13:14:09 -0600943static void build_regrestore_cmds(struct adreno_device *adreno_dev,
944 struct adreno_context *drawctxt)
945{
946 unsigned int *start = tmp_ctx.cmd;
947 unsigned int *cmd = start;
948
949 unsigned int i = 0;
950 unsigned int reg_array_size = 0;
951 const unsigned int *ptr_register_ranges;
952
Jordan Crouse084427d2011-07-28 08:37:58 -0600953 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600954 *cmd++ = 0;
955
956 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -0600957 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -0600958 cmd++;
959#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
960 /* Force mismatch */
961 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
962#else
963 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
964#endif
965
966 /* Based on chip id choose the registers ranges*/
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600967 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600968 ptr_register_ranges = register_ranges_a22x;
969 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
970 } else {
971 ptr_register_ranges = register_ranges_a20x;
972 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
973 }
974
975
976 for (i = 0; i < (reg_array_size/2); i++) {
977 cmd = reg_range(cmd, ptr_register_ranges[i*2],
978 ptr_register_ranges[i*2+1]);
979 }
980
981 /* Now we know how many register blocks we have, we can compute command
982 * length
983 */
984 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -0600985 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600986 /* Enable shadowing for the entire register block. */
987#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
988 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
989#else
990 start[4] |= (1 << 24) | (4 << 16);
991#endif
992
993 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600994 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600995 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
996 *cmd++ = 0x00040400;
997
Jordan Crouse084427d2011-07-28 08:37:58 -0600998 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600999 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001000 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001001 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1002 *cmd++ = 0x00000000;
1003
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001004 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001005 unsigned int i;
1006 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001007 for (i = REG_A220_VSC_BIN_SIZE; i <=
1008 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001009 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001010 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1011 &drawctxt->gpustate);
1012 *cmd++ = 0x00000000;
1013 j++;
1014 }
1015 }
1016
1017 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001018 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001019 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1020#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1021 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1022#else
1023 *cmd++ = (1 << 24) | (0 << 16) | 0;
1024#endif
1025 *cmd++ = ALU_CONSTANTS;
1026
1027 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001028 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001029 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1030#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1031 /* Disable shadowing */
1032 *cmd++ = (0 << 24) | (1 << 16) | 0;
1033#else
1034 *cmd++ = (1 << 24) | (1 << 16) | 0;
1035#endif
1036 *cmd++ = TEX_CONSTANTS;
1037
1038 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001039 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001040 *cmd++ = (2 << 16) | 0;
1041
1042 /* the next BOOL_CONSTANT dwords is the shadow area for
1043 * boolean constants.
1044 */
1045 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1046 cmd += BOOL_CONSTANTS;
1047
1048 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001049 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001050 *cmd++ = (3 << 16) | 0;
1051
1052 /* the next LOOP_CONSTANTS dwords is the shadow area for
1053 * loop constants.
1054 */
1055 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1056 cmd += LOOP_CONSTANTS;
1057
1058 /* create indirect buffer command for above command sequence */
1059 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1060
1061 tmp_ctx.cmd = cmd;
1062}
1063
Jordan Crousea78c9172011-07-11 13:14:09 -06001064static void
1065build_shader_save_restore_cmds(struct adreno_context *drawctxt)
1066{
1067 unsigned int *cmd = tmp_ctx.cmd;
1068 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001069 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001070 unsigned int *partition1;
1071 unsigned int *shaderBases, *partition2;
1072
Jordan Crousea78c9172011-07-11 13:14:09 -06001073 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1074 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
1075 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex + SHADER_SHADOW_SIZE;
1076 tmp_ctx.shader_shared = tmp_ctx.shader_pixel + SHADER_SHADOW_SIZE;
Jordan Crousea78c9172011-07-11 13:14:09 -06001077
1078 /* restore shader partitioning and instructions */
1079
1080 restore = cmd; /* start address */
1081
1082 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001083 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001084 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1085
1086 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001087 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001088 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1089
1090 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001091 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001092 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1093
Jordan Crousea78c9172011-07-11 13:14:09 -06001094 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001095 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001096 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1097 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1098
1099 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001100 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001101 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1102 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1103
1104 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001105 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001106 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1107 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001108
1109 /* create indirect buffer command for above command sequence */
1110 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1111
1112 /*
1113 * fixup SET_SHADER_BASES data
1114 *
1115 * since self-modifying PM4 code is being used here, a seperate
1116 * command buffer is used for this fixup operation, to ensure the
1117 * commands are not read by the PM4 engine before the data fields
1118 * have been written.
1119 */
1120
1121 fixup = cmd; /* start address */
1122
1123 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001124 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001125 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1126
1127 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001128 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001129 *cmd++ = REG_SCRATCH_REG2;
1130 /* AND off invalid bits. */
1131 *cmd++ = 0x0FFF0FFF;
1132 /* OR in instruction memory size */
1133 *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2 - 5U) << 29);
1134
1135 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001136 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001137 *cmd++ = REG_SCRATCH_REG2;
1138 /* TBD #5: shader bases (to restore) */
1139 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1140
1141 /* create indirect buffer command for above command sequence */
1142 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1143
1144 /* save shader partitioning and instructions */
1145
1146 save = cmd; /* start address */
1147
Jordan Crouse084427d2011-07-28 08:37:58 -06001148 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001149 *cmd++ = 0;
1150
1151 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1152 * store the value in the data fields of the SET_CONSTANT commands
1153 * above.
1154 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001155 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001156 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1157 /* TBD #4a: partition info (to restore) */
1158 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001159 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001160 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1161 /* TBD #4b: partition info (to fixup) */
1162 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1163
Jordan Crousea78c9172011-07-11 13:14:09 -06001164
1165 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001166 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001167 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1168 /* TBD #1: start/size (to restore) */
1169 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1170
1171 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001172 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001173 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1174 /* TBD #2: start/size (to restore) */
1175 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1176
1177 /* store the shared shader instructions if vertex base is nonzero */
1178
Jordan Crouse084427d2011-07-28 08:37:58 -06001179 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001180 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1181 /* TBD #3: start/size (to restore) */
1182 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1183
Jordan Crousea78c9172011-07-11 13:14:09 -06001184
Jordan Crouse084427d2011-07-28 08:37:58 -06001185 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001186 *cmd++ = 0;
1187
1188 /* create indirect buffer command for above command sequence */
1189 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1190
1191 tmp_ctx.cmd = cmd;
1192}
1193
1194/* create buffers for saving/restoring registers, constants, & GMEM */
1195static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1196 struct adreno_context *drawctxt)
1197{
1198 int result;
1199
1200 /* Allocate vmalloc memory to store the gpustate */
1201 result = kgsl_allocate(&drawctxt->gpustate,
1202 drawctxt->pagetable, CONTEXT_SIZE);
1203
1204 if (result)
1205 return result;
1206
1207 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1208
1209 /* Blank out h/w register, constant, and command buffer shadows. */
1210 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
1211
1212 /* set-up command and vertex buffer pointers */
1213 tmp_ctx.cmd = tmp_ctx.start
1214 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1215
1216 /* build indirect command buffers to save & restore regs/constants */
1217 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1218 build_regrestore_cmds(adreno_dev, drawctxt);
1219 build_regsave_cmds(adreno_dev, drawctxt);
1220
1221 build_shader_save_restore_cmds(drawctxt);
1222
1223 kgsl_cache_range_op(&drawctxt->gpustate,
1224 KGSL_CACHE_OP_FLUSH);
1225
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001226 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1227 drawctxt->gpustate.gpuaddr,
1228 drawctxt->gpustate.size, false);
Jordan Crousea78c9172011-07-11 13:14:09 -06001229 return 0;
1230}
1231
1232/* create buffers for saving/restoring registers, constants, & GMEM */
1233static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1234 struct adreno_context *drawctxt)
1235{
1236 int result;
1237
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001238 calc_gmemsize(&drawctxt->context_gmem_shadow,
1239 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001240 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1241
1242 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1243 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1244
1245 if (result)
1246 return result;
1247
1248 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1249 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1250
1251 /* blank out gmem shadow. */
1252 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1253 drawctxt->context_gmem_shadow.size);
1254
1255 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001256 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1257 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001258
1259 /* build TP0_CHICKEN register restore command buffer */
1260 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1261
1262 /* build indirect command buffers to save & restore gmem */
1263 /* Idle because we are reading PM override registers */
1264 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1265 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1266 tmp_ctx.cmd =
1267 build_gmem2sys_cmds(adreno_dev, drawctxt,
1268 &drawctxt->context_gmem_shadow);
1269 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1270 tmp_ctx.cmd =
1271 build_sys2gmem_cmds(adreno_dev, drawctxt,
1272 &drawctxt->context_gmem_shadow);
1273
1274 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1275 KGSL_CACHE_OP_FLUSH);
1276
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001277 kgsl_cffdump_syncmem(NULL,
1278 &drawctxt->context_gmem_shadow.gmemshadow,
1279 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1280 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1281
Jordan Crousea78c9172011-07-11 13:14:09 -06001282 return 0;
1283}
1284
1285static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1286 struct adreno_context *context)
1287{
1288 struct kgsl_device *device = &adreno_dev->dev;
1289
1290 if (context == NULL)
1291 return;
1292
1293 if (context->flags & CTXT_FLAGS_GPU_HANG)
1294 KGSL_CTXT_WARN(device,
1295 "Current active context has caused gpu hang\n");
1296
1297 KGSL_CTXT_INFO(device,
1298 "active context flags %08x\n", context->flags);
1299
1300 /* save registers and constants. */
1301 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1302
1303 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1304 /* save shader partitioning and instructions. */
1305 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1306 context->shader_save, 3);
1307
1308 /* fixup shader partitioning parameter for
1309 * SET_SHADER_BASES.
1310 */
1311 adreno_ringbuffer_issuecmds(device, 0,
1312 context->shader_fixup, 3);
1313
1314 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1315 }
1316
1317 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1318 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1319 /* save gmem.
1320 * (note: changes shader. shader must already be saved.)
1321 */
1322 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1323 context->context_gmem_shadow.gmem_save, 3);
1324
1325 /* Restore TP0_CHICKEN */
1326 adreno_ringbuffer_issuecmds(device, 0,
1327 context->chicken_restore, 3);
1328
1329 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
1330 }
1331}
1332
1333static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1334 struct adreno_context *context)
1335{
1336 struct kgsl_device *device = &adreno_dev->dev;
1337 unsigned int cmds[5];
1338
1339 if (context == NULL) {
1340 /* No context - set the default apgetable and thats it */
1341 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1342 return;
1343 }
1344
1345 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1346
Jordan Crouse084427d2011-07-28 08:37:58 -06001347 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001348 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001349 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001350 cmds[3] = device->memstore.gpuaddr +
1351 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1352 cmds[4] = (unsigned int) context;
1353 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1354 kgsl_mmu_setstate(device, context->pagetable);
1355
1356#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1357 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1358 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1359 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1360#endif
1361
1362 /* restore gmem.
1363 * (note: changes shader. shader must not already be restored.)
1364 */
1365 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1366 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1367 context->context_gmem_shadow.gmem_restore, 3);
1368
1369 /* Restore TP0_CHICKEN */
1370 adreno_ringbuffer_issuecmds(device, 0,
1371 context->chicken_restore, 3);
1372
1373 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1374 }
1375
1376 /* restore registers and constants. */
1377 adreno_ringbuffer_issuecmds(device, 0,
1378 context->reg_restore, 3);
1379
1380 /* restore shader instructions & partitioning. */
1381 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1382 adreno_ringbuffer_issuecmds(device, 0,
1383 context->shader_restore, 3);
1384 }
1385
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001386 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001387 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001388 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001389 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001390 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001391}
1392
1393/*
1394 * Interrupt management
1395 *
1396 * a2xx interrupt control is distributed among the various
1397 * hardware components (RB, CP, MMU). The main interrupt
1398 * tells us which component fired the interrupt, but one needs
1399 * to go to the individual component to find out why. The
1400 * following functions provide the broken out support for
1401 * managing the interrupts
1402 */
1403
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001404#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001405
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001406#define CP_INT_MASK \
1407 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001408 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1409 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1410 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1411 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001412 CP_INT_CNTL__IB1_INT_MASK | \
1413 CP_INT_CNTL__RB_INT_MASK)
1414
1415#define VALID_STATUS_COUNT_MAX 10
1416
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001417static struct {
1418 unsigned int mask;
1419 const char *message;
1420} kgsl_cp_error_irqs[] = {
1421 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1422 "ringbuffer TO packet in IB interrupt" },
1423 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1424 "ringbuffer opcode error interrupt" },
1425 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1426 "ringbuffer protected mode error interrupt" },
1427 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1428 "ringbuffer reserved bit error interrupt" },
1429 { CP_INT_CNTL__IB_ERROR_MASK,
1430 "ringbuffer IB error interrupt" },
1431};
1432
Jordan Crousea78c9172011-07-11 13:14:09 -06001433static void a2xx_cp_intrcallback(struct kgsl_device *device)
1434{
1435 unsigned int status = 0, num_reads = 0, master_status = 0;
1436 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1437 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001438 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001439
1440 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1441 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1442 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1443 adreno_regread(device, REG_CP_INT_STATUS, &status);
1444 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1445 &master_status);
1446 num_reads++;
1447 }
1448 if (num_reads > 1)
1449 KGSL_DRV_WARN(device,
1450 "Looped %d times to read REG_CP_INT_STATUS\n",
1451 num_reads);
1452 if (!status) {
1453 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1454 /* This indicates that we could not read CP_INT_STAT.
1455 * As a precaution just wake up processes so
1456 * they can check their timestamps. Since, we
1457 * did not ack any interrupts this interrupt will
1458 * be generated again */
1459 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1460 wake_up_interruptible_all(&device->wait_queue);
1461 } else
1462 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1463 return;
1464 }
1465
1466 if (status & CP_INT_CNTL__RB_INT_MASK) {
1467 /* signal intr completion event */
1468 unsigned int enableflag = 0;
1469 kgsl_sharedmem_writel(&rb->device->memstore,
1470 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1471 enableflag);
1472 wmb();
1473 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1474 }
1475
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001476 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1477 if (status & kgsl_cp_error_irqs[i].mask) {
1478 KGSL_CMD_CRIT(rb->device, "%s\n",
1479 kgsl_cp_error_irqs[i].message);
1480 /*
1481 * on fatal errors, turn off the interrupts to
1482 * avoid storming. This has the side effect of
1483 * forcing a PM dump when the timestamp times out
1484 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001485
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001486 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1487 }
1488 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001489
1490 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001491 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001492 adreno_regwrite(device, REG_CP_INT_ACK, status);
1493
1494 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1495 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
1496 wake_up_interruptible_all(&device->wait_queue);
1497 atomic_notifier_call_chain(&(device->ts_notifier_list),
1498 device->id,
1499 NULL);
1500 }
1501}
1502
1503static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1504{
1505 unsigned int status = 0;
1506 unsigned int rderr = 0;
1507
1508 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1509
1510 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1511 union rbbm_read_error_u rerr;
1512 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1513 rerr.val = rderr;
1514 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1515 rerr.f.read_error &&
1516 rerr.f.read_requester)
1517 KGSL_DRV_WARN(device,
1518 "rbbm read error interrupt: %08x\n", rderr);
1519 else
1520 KGSL_DRV_CRIT(device,
1521 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001522 }
1523
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001524 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001525 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1526}
1527
1528irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1529{
1530 struct kgsl_device *device = &adreno_dev->dev;
1531 irqreturn_t result = IRQ_NONE;
1532 unsigned int status;
1533
1534 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1535
1536 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1537 kgsl_mh_intrcallback(device);
1538 result = IRQ_HANDLED;
1539 }
1540
1541 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1542 a2xx_cp_intrcallback(device);
1543 result = IRQ_HANDLED;
1544 }
1545
1546 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1547 a2xx_rbbm_intrcallback(device);
1548 result = IRQ_HANDLED;
1549 }
1550
1551 return result;
1552}
1553
1554static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1555{
1556 struct kgsl_device *device = &adreno_dev->dev;
1557
1558 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001559 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1560 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001561 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1562 } else {
1563 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1564 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1565 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1566 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001567
1568 /* Force the writes to post before touching the IRQ line */
1569 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001570}
1571
1572struct adreno_gpudev adreno_a2xx_gpudev = {
1573 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1574 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1575 .ctxt_save = a2xx_ctxt_save,
1576 .ctxt_restore = a2xx_ctxt_restore,
1577 .irq_handler = a2xx_irq_handler,
1578 .irq_control = a2xx_irq_control,
1579};