blob: 7b27f61bcc6fab42c4c66f2a71ac5bc40257c0f2 [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 */
Jordan Crousea78c9172011-07-11 13:14:09 -060075
76/* LOAD_CONSTANT_CONTEXT shadow size */
77#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
78
79#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
80#define REG_SHADOW_SIZE 0x1000 /* 4KB */
81#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
82#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
83#else
84#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
85#endif
86#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
Jordan Crousea78c9172011-07-11 13:14:09 -060087
88#define REG_OFFSET LCC_SHADOW_SIZE
89#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
90#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
91#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
92
Jeremy Gebbenddf6b572011-09-09 13:39:49 -070093static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
94{
95 return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
96}
97
98static inline int _context_size(struct adreno_device *adreno_dev)
99{
100 return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
101}
Jordan Crousea78c9172011-07-11 13:14:09 -0600102
103/* A scratchpad used to build commands during context create */
104
105static struct tmp_ctx {
106 unsigned int *start; /* Command & Vertex buffer start */
107 unsigned int *cmd; /* Next available dword in C&V buffer */
108
109 /* address of buffers, needed when creating IB1 command buffers. */
110 uint32_t bool_shadow; /* bool constants */
111 uint32_t loop_shadow; /* loop constants */
112
Jordan Crousea78c9172011-07-11 13:14:09 -0600113 uint32_t shader_shared; /* shared shader instruction shadow */
114 uint32_t shader_vertex; /* vertex shader instruction shadow */
115 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600116
117 /* Addresses in command buffer where separately handled registers
118 * are saved
119 */
120 uint32_t reg_values[33];
121 uint32_t chicken_restore;
122
123 uint32_t gmem_base; /* Base gpu address of GMEM */
124
125} tmp_ctx;
126
127/* context save (gmem -> sys) */
128
129/* pre-compiled vertex shader program
130*
131* attribute vec4 P;
132* void main(void)
133* {
134* gl_Position = P;
135* }
136*/
137#define GMEM2SYS_VTX_PGM_LEN 0x12
138
139static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
140 0x00011003, 0x00001000, 0xc2000000,
141 0x00001004, 0x00001000, 0xc4000000,
142 0x00001005, 0x00002000, 0x00000000,
143 0x1cb81000, 0x00398a88, 0x00000003,
144 0x140f803e, 0x00000000, 0xe2010100,
145 0x14000000, 0x00000000, 0xe2000000
146};
147
148/* pre-compiled fragment shader program
149*
150* precision highp float;
151* uniform vec4 clear_color;
152* void main(void)
153* {
154* gl_FragColor = clear_color;
155* }
156*/
157
158#define GMEM2SYS_FRAG_PGM_LEN 0x0c
159
160static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
161 0x00000000, 0x1002c400, 0x10000000,
162 0x00001003, 0x00002000, 0x00000000,
163 0x140f8000, 0x00000000, 0x22000000,
164 0x14000000, 0x00000000, 0xe2000000
165};
166
167/* context restore (sys -> gmem) */
168/* pre-compiled vertex shader program
169*
170* attribute vec4 position;
171* attribute vec4 texcoord;
172* varying vec4 texcoord0;
173* void main()
174* {
175* gl_Position = position;
176* texcoord0 = texcoord;
177* }
178*/
179
180#define SYS2GMEM_VTX_PGM_LEN 0x18
181
182static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
183 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
184 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
185 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
186 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
187 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
188 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
189};
190
191/* pre-compiled fragment shader program
192*
193* precision mediump float;
194* uniform sampler2D tex0;
195* varying vec4 texcoord0;
196* void main()
197* {
198* gl_FragColor = texture2D(tex0, texcoord0.xy);
199* }
200*/
201
202#define SYS2GMEM_FRAG_PGM_LEN 0x0f
203
204static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
205 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
206 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
207 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
208 0x14000000, 0x00000000, 0xe2000000
209};
210
211/* shader texture constants (sysmem -> gmem) */
212#define SYS2GMEM_TEX_CONST_LEN 6
213
214static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
215 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
216 * RFMode=ZeroClamp-1, Dim=1:2d
217 */
218 0x00000002, /* Pitch = TBD */
219
220 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
221 * NearestClamp=1:OGL Mode
222 */
223 0x00000800, /* Address[31:12] = TBD */
224
225 /* Width, Height, EndianSwap=0:None */
226 0, /* Width & Height = TBD */
227
228 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
229 * Mip=2:BaseMap
230 */
231 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
232
233 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
234 * Dim3d=0
235 */
236 0,
237
238 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
239 * Dim=1:2d, MipPacking=0
240 */
241 1 << 9 /* Mip Address[31:12] = TBD */
242};
243
Jordan Crousea78c9172011-07-11 13:14:09 -0600244#define NUM_COLOR_FORMATS 13
245
246static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
247 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
248 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
249 FMT_5_6_5, /* COLORX_5_6_5 */
250 FMT_8, /* COLORX_8 */
251 FMT_8_8, /* COLORX_8_8 */
252 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
253 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
254 FMT_16_FLOAT, /* COLORX_16_FLOAT */
255 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
256 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
257 FMT_32_FLOAT, /* COLORX_32_FLOAT */
258 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
259 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
260};
261
262static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
263 2, /* COLORX_4_4_4_4 */
264 2, /* COLORX_1_5_5_5 */
265 2, /* COLORX_5_6_5 */
266 1, /* COLORX_8 */
267 2, /* COLORX_8_8 8*/
268 4, /* COLORX_8_8_8_8 */
269 4, /* COLORX_S8_8_8_8 */
270 2, /* COLORX_16_FLOAT */
271 4, /* COLORX_16_16_FLOAT */
272 8, /* COLORX_16_16_16_16_FLOAT */
273 4, /* COLORX_32_FLOAT */
274 8, /* COLORX_32_32_FLOAT */
275 16, /* COLORX_32_32_32_32_FLOAT */
276};
277
278/* shader linkage info */
279#define SHADER_CONST_ADDR (11 * 6 + 3)
280
Jordan Crousea78c9172011-07-11 13:14:09 -0600281
282static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
283 unsigned int *shader_pgm, int dwords)
284{
285 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600286 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600287 /* 0=vertex shader, 1=fragment shader */
288 *cmds++ = vtxfrag;
289 /* instruction start & size (in 32-bit words) */
290 *cmds++ = ((0 << 16) | dwords);
291
292 memcpy(cmds, shader_pgm, dwords << 2);
293 cmds += dwords;
294
295 return cmds;
296}
297
298static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
299 uint32_t src, int dwords)
300{
301 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600302 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600303 *cmds++ = src++;
304 *cmds++ = dst;
305 dst += 4;
306 }
307
308 return cmds;
309}
310
311#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
312
313static void build_reg_to_mem_range(unsigned int start, unsigned int end,
314 unsigned int **cmd,
315 struct adreno_context *drawctxt)
316{
317 unsigned int i = start;
318
319 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600320 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600321 *(*cmd)++ = i;
322 *(*cmd)++ =
323 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
324 (i - 0x2000) * 4;
325 }
326}
327
328#endif
329
330/* chicken restore */
331static unsigned int *build_chicken_restore_cmds(
332 struct adreno_context *drawctxt)
333{
334 unsigned int *start = tmp_ctx.cmd;
335 unsigned int *cmds = start;
336
Jordan Crouse084427d2011-07-28 08:37:58 -0600337 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600338 *cmds++ = 0;
339
Jordan Crouse084427d2011-07-28 08:37:58 -0600340 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600341 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
342 *cmds++ = 0x00000000;
343
344 /* create indirect buffer command for above command sequence */
345 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
346
347 return cmds;
348}
349
350/****************************************************************************/
351/* context save */
352/****************************************************************************/
353
354static const unsigned int register_ranges_a20x[] = {
355 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
356 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
357 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
358 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
359 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
360 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
361 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
362 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
363 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
364 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
365 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
366 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
367 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
368 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
369};
370
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700371static const unsigned int register_ranges_a220[] = {
Jordan Crousea78c9172011-07-11 13:14:09 -0600372 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
373 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
374 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
375 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
376 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
377 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
378 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
379 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
380 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700381 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600382 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
383 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
384 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
385 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
386 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700387 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
388 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600389 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
390};
391
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700392static const unsigned int register_ranges_a225[] = {
393 REG_RB_SURFACE_INFO, REG_A225_RB_COLOR_INFO3,
394 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
395 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
396 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
397 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
398 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
399 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
400 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
401 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
402 REG_A220_PC_MAX_VTX_INDX, REG_A225_PC_MULTI_PRIM_IB_RESET_INDX,
403 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
404 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
405 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
406 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
407 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
408 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
409 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
410 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
Jeremy Gebbene139a042011-11-17 16:20:41 -0700411 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
412 REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700413};
414
Jordan Crousea78c9172011-07-11 13:14:09 -0600415
416/* save h/w regs, alu constants, texture contants, etc. ...
417* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
418*/
419static void build_regsave_cmds(struct adreno_device *adreno_dev,
420 struct adreno_context *drawctxt)
421{
422 unsigned int *start = tmp_ctx.cmd;
423 unsigned int *cmd = start;
424
Jordan Crouse084427d2011-07-28 08:37:58 -0600425 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600426 *cmd++ = 0;
427
428#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
429 /* Make sure the HW context has the correct register values
430 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600431 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600432 *cmd++ = 0;
433
434 {
435 unsigned int i = 0;
436 unsigned int reg_array_size = 0;
437 const unsigned int *ptr_register_ranges;
438
439 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700440 if (adreno_is_a220(adreno_dev)) {
441 ptr_register_ranges = register_ranges_a220;
442 reg_array_size = ARRAY_SIZE(register_ranges_a220);
443 } else if (adreno_is_a225(adreno_dev)) {
444 ptr_register_ranges = register_ranges_a225;
445 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600446 } else {
447 ptr_register_ranges = register_ranges_a20x;
448 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
449 }
450
451
452 /* Write HW registers into shadow */
453 for (i = 0; i < (reg_array_size/2) ; i++) {
454 build_reg_to_mem_range(ptr_register_ranges[i*2],
455 ptr_register_ranges[i*2+1],
456 &cmd, drawctxt);
457 }
458 }
459
460 /* Copy ALU constants */
461 cmd =
462 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
463 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
464
465 /* Copy Tex constants */
466 cmd =
467 reg_to_mem(cmd,
468 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
469 REG_SQ_FETCH_0, TEX_CONSTANTS);
470#else
471
472 /* Insert a wait for idle packet before reading the registers.
473 * This is to fix a hang/reset seen during stress testing. In this
474 * hang, CP encountered a timeout reading SQ's boolean constant
475 * register. There is logic in the HW that blocks reading of this
476 * register when the SQ block is not idle, which we believe is
477 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600478 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600479 *cmd++ = 0;
480
481 /* H/w registers are already shadowed; just need to disable shadowing
482 * to prevent corruption.
483 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600484 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600485 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
486 *cmd++ = 4 << 16; /* regs, start=0 */
487 *cmd++ = 0x0; /* count = 0 */
488
489 /* ALU constants are already shadowed; just need to disable shadowing
490 * to prevent corruption.
491 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600492 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600493 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
494 *cmd++ = 0 << 16; /* ALU, start=0 */
495 *cmd++ = 0x0; /* count = 0 */
496
497 /* Tex constants are already shadowed; just need to disable shadowing
498 * to prevent corruption.
499 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600500 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600501 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
502 *cmd++ = 1 << 16; /* Tex, start=0 */
503 *cmd++ = 0x0; /* count = 0 */
504#endif
505
506 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600507 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600508 *cmd++ = REG_SQ_GPR_MANAGEMENT;
509 *cmd++ = tmp_ctx.reg_values[0];
510
Jordan Crouse084427d2011-07-28 08:37:58 -0600511 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600512 *cmd++ = REG_TP0_CHICKEN;
513 *cmd++ = tmp_ctx.reg_values[1];
514
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600515 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600516 unsigned int i;
517 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700518 for (i = REG_A220_VSC_BIN_SIZE; i <=
519 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600520 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600521 *cmd++ = i;
522 *cmd++ = tmp_ctx.reg_values[j];
523 j++;
524 }
525 }
526
527 /* Copy Boolean constants */
528 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
529 BOOL_CONSTANTS);
530
531 /* Copy Loop constants */
532 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
533 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
534
535 /* create indirect buffer command for above command sequence */
536 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
537
538 tmp_ctx.cmd = cmd;
539}
540
541/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
542static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
543 struct adreno_context *drawctxt,
544 struct gmem_shadow_t *shadow)
545{
546 unsigned int *cmds = shadow->gmem_save_commands;
547 unsigned int *start = cmds;
548 /* Calculate the new offset based on the adjusted base */
549 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
550 unsigned int addr = shadow->gmemshadow.gpuaddr;
551 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
552
553 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600554 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600555 *cmds++ = REG_TP0_CHICKEN;
556
557 *cmds++ = tmp_ctx.chicken_restore;
558
Jordan Crouse084427d2011-07-28 08:37:58 -0600559 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600560 *cmds++ = 0;
561
562 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600563 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600564 *cmds++ = 0x00000000;
565
566 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600567 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600568 *cmds++ = 0x00000000;
569
570 /* program shader */
571
572 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600573 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600574 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
575 *cmds++ = 0;
576 /* valid(?) vtx constant flag & addr */
577 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
578 /* limit = 12 dwords */
579 *cmds++ = 0x00000030;
580
581 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600582 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600583 *cmds++ = 0x1;
584
Jordan Crouse084427d2011-07-28 08:37:58 -0600585 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600586 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600587 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
588 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
589 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
590
Jordan Crouse084427d2011-07-28 08:37:58 -0600591 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600592 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600593 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
594
Jordan Crouse084427d2011-07-28 08:37:58 -0600595 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600596 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600597 *cmds++ = 0x00000c20;
598
Tarun Karra16346b02011-07-24 15:04:26 -0700599 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600600 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700601 *cmds++ = 0x180;
602
603 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600604 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700605 *cmds++ = 0x00003F00;
606
Jordan Crouse084427d2011-07-28 08:37:58 -0600607 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700608 *cmds++ = adreno_encode_istore_size(adreno_dev)
609 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700610
Jordan Crousea78c9172011-07-11 13:14:09 -0600611 /* load the patched vertex shader stream */
612 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
613
614 /* Load the patched fragment shader stream */
615 cmds =
616 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
617
618 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600619 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600620 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600621 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600622 *cmds++ = 0x10018001;
623 else
624 *cmds++ = 0x10010001;
625 *cmds++ = 0x00000008;
626
627 /* resolve */
628
629 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600630 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600631 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600632 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
633 *cmds++ = 0x00000b00;
634
635 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600636 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600637 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600638 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
639
640 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
641 * Base=gmem_base
642 */
643 /* gmem base assumed 4K aligned. */
644 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
645 *cmds++ =
646 (shadow->
647 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
648
649 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600650 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600651 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600652 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600653 *cmds++ = 0x08;
654 else
655 *cmds++ = 0;
656
657 /* set REG_PA_SU_SC_MODE_CNTL
658 * Front_ptype = draw triangles
659 * Back_ptype = draw triangles
660 * Provoking vertex = last
661 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600662 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600663 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600664 *cmds++ = 0x00080240;
665
666 /* Use maximum scissor values -- quad vertices already have the
667 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600668 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600669 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600670 *cmds++ = (0 << 16) | 0;
671 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600672 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600673 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600674 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
675 *cmds++ = (0x1fff << 16) | (0x1fff);
676
677 /* load the viewport so that z scale = clear depth and
678 * z offset = 0.0f
679 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600680 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600681 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600682 *cmds++ = 0xbf800000; /* -1.0f */
683 *cmds++ = 0x0;
684
Jordan Crouse084427d2011-07-28 08:37:58 -0600685 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600686 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600687 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
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_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600691 *cmds++ = 0xffffffff;
692
Jordan Crouse084427d2011-07-28 08:37:58 -0600693 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600694 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600695 *cmds++ = 0x00000000;
696 *cmds++ = 0x00000000;
697
698 /* load the stencil ref value
699 * $AAM - do this later
700 */
701
702 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600703 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600704 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600705 *cmds++ = 0; /* RB_COPY_CONTROL */
706 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
707 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
708
709 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
710 * MaskWrite:R=G=B=A=1
711 */
712 *cmds++ = 0x0003c008 |
713 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
714 /* Make sure we stay in offsetx field. */
715 BUG_ON(offset & 0xfffff000);
716 *cmds++ = offset;
717
Jordan Crouse084427d2011-07-28 08:37:58 -0600718 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600719 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600720 *cmds++ = 0x6; /* EDRAM copy */
721
Jordan Crouse084427d2011-07-28 08:37:58 -0600722 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600723 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600724 *cmds++ = 0x00010000;
725
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600726 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600727 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600728 *cmds++ = 0;
729
Jordan Crouse084427d2011-07-28 08:37:58 -0600730 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700731 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600732 *cmds++ = 0x0000000;
733
Jordan Crouse084427d2011-07-28 08:37:58 -0600734 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600735 *cmds++ = 0; /* viz query info. */
736 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
737 *cmds++ = 0x00004088;
738 *cmds++ = 3; /* NumIndices=3 */
739 } else {
740 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600741 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600742 *cmds++ = 0; /* viz query info. */
743 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
744 *cmds++ = 0x00030088;
745 }
746
747 /* create indirect buffer command for above command sequence */
748 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
749
750 return cmds;
751}
752
753/* context restore */
754
755/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
756static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
757 struct adreno_context *drawctxt,
758 struct gmem_shadow_t *shadow)
759{
760 unsigned int *cmds = shadow->gmem_restore_commands;
761 unsigned int *start = cmds;
762
763 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600764 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600765 *cmds++ = REG_TP0_CHICKEN;
766 *cmds++ = tmp_ctx.chicken_restore;
767
Jordan Crouse084427d2011-07-28 08:37:58 -0600768 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600769 *cmds++ = 0;
770
771 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600772 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600773 *cmds++ = 0x00000000;
774
775 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600776 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600777 *cmds++ = 0x00000000;
778 /* shader constants */
779
780 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600781 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600782
783 *cmds++ = (0x1 << 16) | (9 * 6);
784 /* valid(?) vtx constant flag & addr */
785 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
786 /* limit = 12 dwords */
787 *cmds++ = 0x00000030;
788 /* valid(?) vtx constant flag & addr */
789 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
790 /* limit = 8 dwords */
791 *cmds++ = 0x00000020;
792 *cmds++ = 0;
793 *cmds++ = 0;
794
795 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600796 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600797 *cmds++ = 0x1;
798
799 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
800
Tarun Karra16346b02011-07-24 15:04:26 -0700801 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600802 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700803 *cmds++ = 0x180;
804
805 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600806 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700807 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
808
Jordan Crouse084427d2011-07-28 08:37:58 -0600809 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700810 *cmds++ = adreno_encode_istore_size(adreno_dev)
811 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700812
Jordan Crousea78c9172011-07-11 13:14:09 -0600813 /* Load the patched fragment shader stream */
814 cmds =
815 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
816
817 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600818 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600819 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600820 *cmds++ = 0x10030002;
821 *cmds++ = 0x00000008;
822
Jordan Crouse084427d2011-07-28 08:37:58 -0600823 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600824 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600825 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
826
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600827 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600828 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600829 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600830 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600831 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
832 }
833
834 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600835 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600836 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600837 *cmds++ = 0x00000c20;
838
Jordan Crouse084427d2011-07-28 08:37:58 -0600839 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600840 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600841 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
842 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
843 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
844
Jordan Crouse084427d2011-07-28 08:37:58 -0600845 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600846 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600847 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
848 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
849
Jordan Crouse084427d2011-07-28 08:37:58 -0600850 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600851 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600852 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
853
Jordan Crouse084427d2011-07-28 08:37:58 -0600854 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600855 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600856 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
857
858 /* set REG_PA_SU_SC_MODE_CNTL
859 * Front_ptype = draw triangles
860 * Back_ptype = draw triangles
861 * Provoking vertex = last
862 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600863 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600864 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600865 *cmds++ = 0x00080240;
866
867 /* texture constants */
868 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600869 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600870 *cmds++ = (0x1 << 16) | (0 * 6);
871 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
872 cmds[0] |= (shadow->pitch >> 5) << 22;
873 cmds[1] |=
874 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
875 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
876 cmds += SYS2GMEM_TEX_CONST_LEN;
877
878 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600879 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600880 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600881 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
882
883 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
884 * Base=gmem_base
885 */
886 *cmds++ =
887 (shadow->
888 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
889
890 /* RB_DEPTHCONTROL */
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_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600893
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600894 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600895 *cmds++ = 8; /* disable Z */
896 else
897 *cmds++ = 0; /* disable Z */
898
899 /* Use maximum scissor values -- quad vertices already
900 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600901 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600902 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600903 *cmds++ = (0 << 16) | 0;
904 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600905 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600906 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600907 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
908 *cmds++ = ((0x1fff) << 16) | 0x1fff;
909
Jordan Crouse084427d2011-07-28 08:37:58 -0600910 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600911 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600912 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
913 *cmds++ = 0x00000b00;
914
915 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600916 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600917 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600918 *cmds++ = 0xbf800000;
919 *cmds++ = 0x0;
920
Jordan Crouse084427d2011-07-28 08:37:58 -0600921 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600922 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600923 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
924
Jordan Crouse084427d2011-07-28 08:37:58 -0600925 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600926 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600927 *cmds++ = 0xffffffff;
928
Jordan Crouse084427d2011-07-28 08:37:58 -0600929 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600930 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600931 *cmds++ = 0x00000000;
932 *cmds++ = 0x00000000;
933
934 /* load the stencil ref value
935 * $AAM - do this later
936 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600937 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600938 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600939 /* draw pixels with color and depth/stencil component */
940 *cmds++ = 0x4;
941
Jordan Crouse084427d2011-07-28 08:37:58 -0600942 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600943 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600944 *cmds++ = 0x00010000;
945
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600946 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600947 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600948 *cmds++ = 0;
949
Jordan Crouse084427d2011-07-28 08:37:58 -0600950 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700951 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600952 *cmds++ = 0x0000000;
953
Jordan Crouse084427d2011-07-28 08:37:58 -0600954 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600955 *cmds++ = 0; /* viz query info. */
956 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
957 *cmds++ = 0x00004088;
958 *cmds++ = 3; /* NumIndices=3 */
959 } else {
960 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600961 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600962 *cmds++ = 0; /* viz query info. */
963 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
964 *cmds++ = 0x00030088;
965 }
966
967 /* create indirect buffer command for above command sequence */
968 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
969
970 return cmds;
971}
972
Jordan Crousea78c9172011-07-11 13:14:09 -0600973static void build_regrestore_cmds(struct adreno_device *adreno_dev,
974 struct adreno_context *drawctxt)
975{
976 unsigned int *start = tmp_ctx.cmd;
977 unsigned int *cmd = start;
978
979 unsigned int i = 0;
980 unsigned int reg_array_size = 0;
981 const unsigned int *ptr_register_ranges;
982
Jordan Crouse084427d2011-07-28 08:37:58 -0600983 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600984 *cmd++ = 0;
985
986 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -0600987 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -0600988 cmd++;
989#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
990 /* Force mismatch */
991 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
992#else
993 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
994#endif
995
996 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700997 if (adreno_is_a220(adreno_dev)) {
998 ptr_register_ranges = register_ranges_a220;
999 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1000 } else if (adreno_is_a225(adreno_dev)) {
1001 ptr_register_ranges = register_ranges_a225;
1002 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001003 } else {
1004 ptr_register_ranges = register_ranges_a20x;
1005 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1006 }
1007
1008
1009 for (i = 0; i < (reg_array_size/2); i++) {
1010 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1011 ptr_register_ranges[i*2+1]);
1012 }
1013
1014 /* Now we know how many register blocks we have, we can compute command
1015 * length
1016 */
1017 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001018 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001019 /* Enable shadowing for the entire register block. */
1020#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1021 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1022#else
1023 start[4] |= (1 << 24) | (4 << 16);
1024#endif
1025
1026 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001027 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001028 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1029 *cmd++ = 0x00040400;
1030
Jordan Crouse084427d2011-07-28 08:37:58 -06001031 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001032 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001033 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001034 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1035 *cmd++ = 0x00000000;
1036
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001037 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001038 unsigned int i;
1039 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001040 for (i = REG_A220_VSC_BIN_SIZE; i <=
1041 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001042 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001043 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1044 &drawctxt->gpustate);
1045 *cmd++ = 0x00000000;
1046 j++;
1047 }
1048 }
1049
1050 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001051 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001052 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1053#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1054 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1055#else
1056 *cmd++ = (1 << 24) | (0 << 16) | 0;
1057#endif
1058 *cmd++ = ALU_CONSTANTS;
1059
1060 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001061 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001062 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1063#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1064 /* Disable shadowing */
1065 *cmd++ = (0 << 24) | (1 << 16) | 0;
1066#else
1067 *cmd++ = (1 << 24) | (1 << 16) | 0;
1068#endif
1069 *cmd++ = TEX_CONSTANTS;
1070
1071 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001072 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001073 *cmd++ = (2 << 16) | 0;
1074
1075 /* the next BOOL_CONSTANT dwords is the shadow area for
1076 * boolean constants.
1077 */
1078 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1079 cmd += BOOL_CONSTANTS;
1080
1081 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001082 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001083 *cmd++ = (3 << 16) | 0;
1084
1085 /* the next LOOP_CONSTANTS dwords is the shadow area for
1086 * loop constants.
1087 */
1088 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1089 cmd += LOOP_CONSTANTS;
1090
1091 /* create indirect buffer command for above command sequence */
1092 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1093
1094 tmp_ctx.cmd = cmd;
1095}
1096
Jordan Crousea78c9172011-07-11 13:14:09 -06001097static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001098build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1099 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001100{
1101 unsigned int *cmd = tmp_ctx.cmd;
1102 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001103 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001104 unsigned int *partition1;
1105 unsigned int *shaderBases, *partition2;
1106
Jordan Crousea78c9172011-07-11 13:14:09 -06001107 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1108 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001109 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1110 + _shader_shadow_size(adreno_dev);
1111 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1112 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001113
1114 /* restore shader partitioning and instructions */
1115
1116 restore = cmd; /* start address */
1117
1118 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001119 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001120 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1121
1122 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001123 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001124 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1125
1126 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001127 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001128 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1129
Jordan Crousea78c9172011-07-11 13:14:09 -06001130 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001131 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001132 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1133 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1134
1135 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001136 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001137 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1138 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1139
1140 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001141 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001142 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1143 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001144
1145 /* create indirect buffer command for above command sequence */
1146 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1147
1148 /*
1149 * fixup SET_SHADER_BASES data
1150 *
1151 * since self-modifying PM4 code is being used here, a seperate
1152 * command buffer is used for this fixup operation, to ensure the
1153 * commands are not read by the PM4 engine before the data fields
1154 * have been written.
1155 */
1156
1157 fixup = cmd; /* start address */
1158
1159 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001160 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001161 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1162
1163 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001164 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001165 *cmd++ = REG_SCRATCH_REG2;
1166 /* AND off invalid bits. */
1167 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001168 /* OR in instruction memory size. */
1169 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001170
1171 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001172 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001173 *cmd++ = REG_SCRATCH_REG2;
1174 /* TBD #5: shader bases (to restore) */
1175 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1176
1177 /* create indirect buffer command for above command sequence */
1178 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1179
1180 /* save shader partitioning and instructions */
1181
1182 save = cmd; /* start address */
1183
Jordan Crouse084427d2011-07-28 08:37:58 -06001184 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001185 *cmd++ = 0;
1186
1187 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1188 * store the value in the data fields of the SET_CONSTANT commands
1189 * above.
1190 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001191 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001192 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1193 /* TBD #4a: partition info (to restore) */
1194 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001195 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001196 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1197 /* TBD #4b: partition info (to fixup) */
1198 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1199
Jordan Crousea78c9172011-07-11 13:14:09 -06001200
1201 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001202 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001203 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1204 /* TBD #1: start/size (to restore) */
1205 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1206
1207 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001208 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001209 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1210 /* TBD #2: start/size (to restore) */
1211 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1212
1213 /* store the shared shader instructions if vertex base is nonzero */
1214
Jordan Crouse084427d2011-07-28 08:37:58 -06001215 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001216 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1217 /* TBD #3: start/size (to restore) */
1218 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1219
Jordan Crousea78c9172011-07-11 13:14:09 -06001220
Jordan Crouse084427d2011-07-28 08:37:58 -06001221 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001222 *cmd++ = 0;
1223
1224 /* create indirect buffer command for above command sequence */
1225 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1226
1227 tmp_ctx.cmd = cmd;
1228}
1229
1230/* create buffers for saving/restoring registers, constants, & GMEM */
1231static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1232 struct adreno_context *drawctxt)
1233{
1234 int result;
1235
1236 /* Allocate vmalloc memory to store the gpustate */
1237 result = kgsl_allocate(&drawctxt->gpustate,
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001238 drawctxt->pagetable, _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001239
1240 if (result)
1241 return result;
1242
1243 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1244
1245 /* Blank out h/w register, constant, and command buffer shadows. */
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001246 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1247 _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001248
1249 /* set-up command and vertex buffer pointers */
1250 tmp_ctx.cmd = tmp_ctx.start
1251 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1252
1253 /* build indirect command buffers to save & restore regs/constants */
1254 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1255 build_regrestore_cmds(adreno_dev, drawctxt);
1256 build_regsave_cmds(adreno_dev, drawctxt);
1257
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001258 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001259
1260 kgsl_cache_range_op(&drawctxt->gpustate,
1261 KGSL_CACHE_OP_FLUSH);
1262
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001263 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1264 drawctxt->gpustate.gpuaddr,
1265 drawctxt->gpustate.size, false);
Jordan Crousea78c9172011-07-11 13:14:09 -06001266 return 0;
1267}
1268
1269/* create buffers for saving/restoring registers, constants, & GMEM */
1270static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1271 struct adreno_context *drawctxt)
1272{
1273 int result;
1274
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001275 calc_gmemsize(&drawctxt->context_gmem_shadow,
1276 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001277 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1278
1279 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1280 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1281
1282 if (result)
1283 return result;
1284
1285 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1286 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1287
1288 /* blank out gmem shadow. */
1289 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1290 drawctxt->context_gmem_shadow.size);
1291
1292 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001293 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1294 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001295
1296 /* build TP0_CHICKEN register restore command buffer */
1297 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1298
1299 /* build indirect command buffers to save & restore gmem */
1300 /* Idle because we are reading PM override registers */
1301 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1302 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1303 tmp_ctx.cmd =
1304 build_gmem2sys_cmds(adreno_dev, drawctxt,
1305 &drawctxt->context_gmem_shadow);
1306 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1307 tmp_ctx.cmd =
1308 build_sys2gmem_cmds(adreno_dev, drawctxt,
1309 &drawctxt->context_gmem_shadow);
1310
1311 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1312 KGSL_CACHE_OP_FLUSH);
1313
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001314 kgsl_cffdump_syncmem(NULL,
1315 &drawctxt->context_gmem_shadow.gmemshadow,
1316 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1317 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1318
Jordan Crousea78c9172011-07-11 13:14:09 -06001319 return 0;
1320}
1321
1322static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1323 struct adreno_context *context)
1324{
1325 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001326 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001327
1328 if (context == NULL)
1329 return;
1330
1331 if (context->flags & CTXT_FLAGS_GPU_HANG)
1332 KGSL_CTXT_WARN(device,
1333 "Current active context has caused gpu hang\n");
1334
1335 KGSL_CTXT_INFO(device,
1336 "active context flags %08x\n", context->flags);
1337
1338 /* save registers and constants. */
1339 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1340
1341 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1342 /* save shader partitioning and instructions. */
1343 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1344 context->shader_save, 3);
1345
1346 /* fixup shader partitioning parameter for
1347 * SET_SHADER_BASES.
1348 */
1349 adreno_ringbuffer_issuecmds(device, 0,
1350 context->shader_fixup, 3);
1351
1352 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1353 }
1354
1355 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1356 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1357 /* save gmem.
1358 * (note: changes shader. shader must already be saved.)
1359 */
1360 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1361 context->context_gmem_shadow.gmem_save, 3);
1362
1363 /* Restore TP0_CHICKEN */
1364 adreno_ringbuffer_issuecmds(device, 0,
1365 context->chicken_restore, 3);
1366
1367 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001368 } else if (adreno_is_a225(adreno_dev)) {
1369 unsigned int *cmds = &cmd[0];
1370 /*
1371 * Issue an empty draw call to avoid possible hangs due to
1372 * repeated idles without intervening draw calls.
1373 * On adreno 225 the PC block has a cache that is only
1374 * flushed on draw calls and repeated idles can make it
1375 * overflow. The gmem save path contains draw calls so
1376 * this workaround isn't needed there.
1377 */
1378 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1379 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1380 *cmds++ = 0;
1381 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1382 *cmds++ = 0;
1383 *cmds++ = 1<<14;
1384 *cmds++ = 0;
1385 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1386 *cmds++ = 0;
1387 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1388 *cmds++ = 0x00000000;
1389
1390 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1391 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001392 }
1393}
1394
1395static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1396 struct adreno_context *context)
1397{
1398 struct kgsl_device *device = &adreno_dev->dev;
1399 unsigned int cmds[5];
1400
1401 if (context == NULL) {
1402 /* No context - set the default apgetable and thats it */
1403 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1404 return;
1405 }
1406
1407 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1408
Jordan Crouse084427d2011-07-28 08:37:58 -06001409 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001410 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001411 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001412 cmds[3] = device->memstore.gpuaddr +
1413 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1414 cmds[4] = (unsigned int) context;
1415 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1416 kgsl_mmu_setstate(device, context->pagetable);
1417
1418#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1419 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1420 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1421 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1422#endif
1423
1424 /* restore gmem.
1425 * (note: changes shader. shader must not already be restored.)
1426 */
1427 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1428 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1429 context->context_gmem_shadow.gmem_restore, 3);
1430
1431 /* Restore TP0_CHICKEN */
1432 adreno_ringbuffer_issuecmds(device, 0,
1433 context->chicken_restore, 3);
1434
1435 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1436 }
1437
1438 /* restore registers and constants. */
1439 adreno_ringbuffer_issuecmds(device, 0,
1440 context->reg_restore, 3);
1441
1442 /* restore shader instructions & partitioning. */
1443 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1444 adreno_ringbuffer_issuecmds(device, 0,
1445 context->shader_restore, 3);
1446 }
1447
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001448 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001449 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001450 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001451 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001452 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001453}
1454
1455/*
1456 * Interrupt management
1457 *
1458 * a2xx interrupt control is distributed among the various
1459 * hardware components (RB, CP, MMU). The main interrupt
1460 * tells us which component fired the interrupt, but one needs
1461 * to go to the individual component to find out why. The
1462 * following functions provide the broken out support for
1463 * managing the interrupts
1464 */
1465
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001466#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001467
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001468#define CP_INT_MASK \
1469 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001470 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1471 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1472 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1473 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001474 CP_INT_CNTL__IB1_INT_MASK | \
1475 CP_INT_CNTL__RB_INT_MASK)
1476
1477#define VALID_STATUS_COUNT_MAX 10
1478
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001479static struct {
1480 unsigned int mask;
1481 const char *message;
1482} kgsl_cp_error_irqs[] = {
1483 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1484 "ringbuffer TO packet in IB interrupt" },
1485 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1486 "ringbuffer opcode error interrupt" },
1487 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1488 "ringbuffer protected mode error interrupt" },
1489 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1490 "ringbuffer reserved bit error interrupt" },
1491 { CP_INT_CNTL__IB_ERROR_MASK,
1492 "ringbuffer IB error interrupt" },
1493};
1494
Jordan Crousea78c9172011-07-11 13:14:09 -06001495static void a2xx_cp_intrcallback(struct kgsl_device *device)
1496{
1497 unsigned int status = 0, num_reads = 0, master_status = 0;
1498 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1499 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001500 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001501
1502 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1503 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1504 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1505 adreno_regread(device, REG_CP_INT_STATUS, &status);
1506 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1507 &master_status);
1508 num_reads++;
1509 }
1510 if (num_reads > 1)
1511 KGSL_DRV_WARN(device,
1512 "Looped %d times to read REG_CP_INT_STATUS\n",
1513 num_reads);
1514 if (!status) {
1515 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1516 /* This indicates that we could not read CP_INT_STAT.
1517 * As a precaution just wake up processes so
1518 * they can check their timestamps. Since, we
1519 * did not ack any interrupts this interrupt will
1520 * be generated again */
1521 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1522 wake_up_interruptible_all(&device->wait_queue);
1523 } else
1524 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1525 return;
1526 }
1527
1528 if (status & CP_INT_CNTL__RB_INT_MASK) {
1529 /* signal intr completion event */
1530 unsigned int enableflag = 0;
1531 kgsl_sharedmem_writel(&rb->device->memstore,
1532 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1533 enableflag);
1534 wmb();
1535 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1536 }
1537
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001538 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1539 if (status & kgsl_cp_error_irqs[i].mask) {
1540 KGSL_CMD_CRIT(rb->device, "%s\n",
1541 kgsl_cp_error_irqs[i].message);
1542 /*
1543 * on fatal errors, turn off the interrupts to
1544 * avoid storming. This has the side effect of
1545 * forcing a PM dump when the timestamp times out
1546 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001547
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001548 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1549 }
1550 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001551
1552 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001553 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001554 adreno_regwrite(device, REG_CP_INT_ACK, status);
1555
1556 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1557 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001558 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001559 wake_up_interruptible_all(&device->wait_queue);
1560 atomic_notifier_call_chain(&(device->ts_notifier_list),
1561 device->id,
1562 NULL);
1563 }
1564}
1565
1566static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1567{
1568 unsigned int status = 0;
1569 unsigned int rderr = 0;
1570
1571 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1572
1573 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1574 union rbbm_read_error_u rerr;
1575 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1576 rerr.val = rderr;
1577 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1578 rerr.f.read_error &&
1579 rerr.f.read_requester)
1580 KGSL_DRV_WARN(device,
1581 "rbbm read error interrupt: %08x\n", rderr);
1582 else
1583 KGSL_DRV_CRIT(device,
1584 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001585 }
1586
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001587 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001588 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1589}
1590
1591irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1592{
1593 struct kgsl_device *device = &adreno_dev->dev;
1594 irqreturn_t result = IRQ_NONE;
1595 unsigned int status;
1596
1597 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1598
1599 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1600 kgsl_mh_intrcallback(device);
1601 result = IRQ_HANDLED;
1602 }
1603
1604 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1605 a2xx_cp_intrcallback(device);
1606 result = IRQ_HANDLED;
1607 }
1608
1609 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1610 a2xx_rbbm_intrcallback(device);
1611 result = IRQ_HANDLED;
1612 }
1613
1614 return result;
1615}
1616
1617static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1618{
1619 struct kgsl_device *device = &adreno_dev->dev;
1620
1621 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001622 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1623 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001624 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1625 } else {
1626 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1627 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1628 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1629 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001630
1631 /* Force the writes to post before touching the IRQ line */
1632 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001633}
1634
1635struct adreno_gpudev adreno_a2xx_gpudev = {
1636 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1637 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1638 .ctxt_save = a2xx_ctxt_save,
1639 .ctxt_restore = a2xx_ctxt_restore,
1640 .irq_handler = a2xx_irq_handler,
1641 .irq_control = a2xx_irq_control,
1642};