blob: f8ae18a41191a52ec413d635534438595f0a9f15 [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,
378 /* all the below registers are specific to Leia */
379 REG_LEIA_PC_MAX_VTX_INDX, REG_LEIA_PC_INDX_OFFSET,
380 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,
385 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
386 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
387 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;
490 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
491 REG_LEIA_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);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600702 *cmds++ = CP_REG(REG_LEIA_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);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600921 *cmds++ = CP_REG(REG_LEIA_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;
1007 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
1008 REG_LEIA_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
1226 return 0;
1227}
1228
1229/* create buffers for saving/restoring registers, constants, & GMEM */
1230static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1231 struct adreno_context *drawctxt)
1232{
1233 int result;
1234
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001235 calc_gmemsize(&drawctxt->context_gmem_shadow,
1236 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001237 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1238
1239 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1240 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1241
1242 if (result)
1243 return result;
1244
1245 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1246 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1247
1248 /* blank out gmem shadow. */
1249 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1250 drawctxt->context_gmem_shadow.size);
1251
1252 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001253 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1254 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001255
1256 /* build TP0_CHICKEN register restore command buffer */
1257 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1258
1259 /* build indirect command buffers to save & restore gmem */
1260 /* Idle because we are reading PM override registers */
1261 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1262 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1263 tmp_ctx.cmd =
1264 build_gmem2sys_cmds(adreno_dev, drawctxt,
1265 &drawctxt->context_gmem_shadow);
1266 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1267 tmp_ctx.cmd =
1268 build_sys2gmem_cmds(adreno_dev, drawctxt,
1269 &drawctxt->context_gmem_shadow);
1270
1271 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1272 KGSL_CACHE_OP_FLUSH);
1273
1274 return 0;
1275}
1276
1277static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1278 struct adreno_context *context)
1279{
1280 struct kgsl_device *device = &adreno_dev->dev;
1281
1282 if (context == NULL)
1283 return;
1284
1285 if (context->flags & CTXT_FLAGS_GPU_HANG)
1286 KGSL_CTXT_WARN(device,
1287 "Current active context has caused gpu hang\n");
1288
1289 KGSL_CTXT_INFO(device,
1290 "active context flags %08x\n", context->flags);
1291
1292 /* save registers and constants. */
1293 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1294
1295 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1296 /* save shader partitioning and instructions. */
1297 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1298 context->shader_save, 3);
1299
1300 /* fixup shader partitioning parameter for
1301 * SET_SHADER_BASES.
1302 */
1303 adreno_ringbuffer_issuecmds(device, 0,
1304 context->shader_fixup, 3);
1305
1306 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1307 }
1308
1309 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1310 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1311 /* save gmem.
1312 * (note: changes shader. shader must already be saved.)
1313 */
1314 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1315 context->context_gmem_shadow.gmem_save, 3);
1316
1317 /* Restore TP0_CHICKEN */
1318 adreno_ringbuffer_issuecmds(device, 0,
1319 context->chicken_restore, 3);
1320
1321 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
1322 }
1323}
1324
1325static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1326 struct adreno_context *context)
1327{
1328 struct kgsl_device *device = &adreno_dev->dev;
1329 unsigned int cmds[5];
1330
1331 if (context == NULL) {
1332 /* No context - set the default apgetable and thats it */
1333 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1334 return;
1335 }
1336
1337 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1338
Jordan Crouse084427d2011-07-28 08:37:58 -06001339 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001340 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001341 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001342 cmds[3] = device->memstore.gpuaddr +
1343 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1344 cmds[4] = (unsigned int) context;
1345 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1346 kgsl_mmu_setstate(device, context->pagetable);
1347
1348#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1349 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1350 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1351 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1352#endif
1353
1354 /* restore gmem.
1355 * (note: changes shader. shader must not already be restored.)
1356 */
1357 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1358 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1359 context->context_gmem_shadow.gmem_restore, 3);
1360
1361 /* Restore TP0_CHICKEN */
1362 adreno_ringbuffer_issuecmds(device, 0,
1363 context->chicken_restore, 3);
1364
1365 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1366 }
1367
1368 /* restore registers and constants. */
1369 adreno_ringbuffer_issuecmds(device, 0,
1370 context->reg_restore, 3);
1371
1372 /* restore shader instructions & partitioning. */
1373 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1374 adreno_ringbuffer_issuecmds(device, 0,
1375 context->shader_restore, 3);
1376 }
1377
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001378 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001379 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001380 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001381 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001382 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001383}
1384
1385/*
1386 * Interrupt management
1387 *
1388 * a2xx interrupt control is distributed among the various
1389 * hardware components (RB, CP, MMU). The main interrupt
1390 * tells us which component fired the interrupt, but one needs
1391 * to go to the individual component to find out why. The
1392 * following functions provide the broken out support for
1393 * managing the interrupts
1394 */
1395
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001396#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001397
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001398#define CP_INT_MASK \
1399 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001400 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1401 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1402 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1403 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001404 CP_INT_CNTL__IB1_INT_MASK | \
1405 CP_INT_CNTL__RB_INT_MASK)
1406
1407#define VALID_STATUS_COUNT_MAX 10
1408
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001409static struct {
1410 unsigned int mask;
1411 const char *message;
1412} kgsl_cp_error_irqs[] = {
1413 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1414 "ringbuffer TO packet in IB interrupt" },
1415 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1416 "ringbuffer opcode error interrupt" },
1417 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1418 "ringbuffer protected mode error interrupt" },
1419 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1420 "ringbuffer reserved bit error interrupt" },
1421 { CP_INT_CNTL__IB_ERROR_MASK,
1422 "ringbuffer IB error interrupt" },
1423};
1424
Jordan Crousea78c9172011-07-11 13:14:09 -06001425static void a2xx_cp_intrcallback(struct kgsl_device *device)
1426{
1427 unsigned int status = 0, num_reads = 0, master_status = 0;
1428 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1429 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001430 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001431
1432 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1433 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1434 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1435 adreno_regread(device, REG_CP_INT_STATUS, &status);
1436 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1437 &master_status);
1438 num_reads++;
1439 }
1440 if (num_reads > 1)
1441 KGSL_DRV_WARN(device,
1442 "Looped %d times to read REG_CP_INT_STATUS\n",
1443 num_reads);
1444 if (!status) {
1445 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1446 /* This indicates that we could not read CP_INT_STAT.
1447 * As a precaution just wake up processes so
1448 * they can check their timestamps. Since, we
1449 * did not ack any interrupts this interrupt will
1450 * be generated again */
1451 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1452 wake_up_interruptible_all(&device->wait_queue);
1453 } else
1454 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1455 return;
1456 }
1457
1458 if (status & CP_INT_CNTL__RB_INT_MASK) {
1459 /* signal intr completion event */
1460 unsigned int enableflag = 0;
1461 kgsl_sharedmem_writel(&rb->device->memstore,
1462 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1463 enableflag);
1464 wmb();
1465 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1466 }
1467
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001468 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1469 if (status & kgsl_cp_error_irqs[i].mask) {
1470 KGSL_CMD_CRIT(rb->device, "%s\n",
1471 kgsl_cp_error_irqs[i].message);
1472 /*
1473 * on fatal errors, turn off the interrupts to
1474 * avoid storming. This has the side effect of
1475 * forcing a PM dump when the timestamp times out
1476 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001477
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001478 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1479 }
1480 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001481
1482 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001483 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001484 adreno_regwrite(device, REG_CP_INT_ACK, status);
1485
1486 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1487 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
1488 wake_up_interruptible_all(&device->wait_queue);
1489 atomic_notifier_call_chain(&(device->ts_notifier_list),
1490 device->id,
1491 NULL);
1492 }
1493}
1494
1495static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1496{
1497 unsigned int status = 0;
1498 unsigned int rderr = 0;
1499
1500 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1501
1502 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1503 union rbbm_read_error_u rerr;
1504 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1505 rerr.val = rderr;
1506 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1507 rerr.f.read_error &&
1508 rerr.f.read_requester)
1509 KGSL_DRV_WARN(device,
1510 "rbbm read error interrupt: %08x\n", rderr);
1511 else
1512 KGSL_DRV_CRIT(device,
1513 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001514 }
1515
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001516 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001517 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1518}
1519
1520irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1521{
1522 struct kgsl_device *device = &adreno_dev->dev;
1523 irqreturn_t result = IRQ_NONE;
1524 unsigned int status;
1525
1526 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1527
1528 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1529 kgsl_mh_intrcallback(device);
1530 result = IRQ_HANDLED;
1531 }
1532
1533 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1534 a2xx_cp_intrcallback(device);
1535 result = IRQ_HANDLED;
1536 }
1537
1538 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1539 a2xx_rbbm_intrcallback(device);
1540 result = IRQ_HANDLED;
1541 }
1542
1543 return result;
1544}
1545
1546static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1547{
1548 struct kgsl_device *device = &adreno_dev->dev;
1549
1550 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001551 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1552 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001553 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1554 } else {
1555 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1556 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1557 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1558 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001559
1560 /* Force the writes to post before touching the IRQ line */
1561 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001562}
1563
1564struct adreno_gpudev adreno_a2xx_gpudev = {
1565 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1566 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1567 .ctxt_save = a2xx_ctxt_save,
1568 .ctxt_restore = a2xx_ctxt_restore,
1569 .irq_handler = a2xx_irq_handler,
1570 .irq_control = a2xx_irq_control,
1571};