blob: 5acf23d0c51f49b1e3e9e44999af24157df7a518 [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,
411 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP_ENABLED
412};
413
Jordan Crousea78c9172011-07-11 13:14:09 -0600414
415/* save h/w regs, alu constants, texture contants, etc. ...
416* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
417*/
418static void build_regsave_cmds(struct adreno_device *adreno_dev,
419 struct adreno_context *drawctxt)
420{
421 unsigned int *start = tmp_ctx.cmd;
422 unsigned int *cmd = start;
423
Jordan Crouse084427d2011-07-28 08:37:58 -0600424 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600425 *cmd++ = 0;
426
427#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
428 /* Make sure the HW context has the correct register values
429 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600430 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600431 *cmd++ = 0;
432
433 {
434 unsigned int i = 0;
435 unsigned int reg_array_size = 0;
436 const unsigned int *ptr_register_ranges;
437
438 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700439 if (adreno_is_a220(adreno_dev)) {
440 ptr_register_ranges = register_ranges_a220;
441 reg_array_size = ARRAY_SIZE(register_ranges_a220);
442 } else if (adreno_is_a225(adreno_dev)) {
443 ptr_register_ranges = register_ranges_a225;
444 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600445 } else {
446 ptr_register_ranges = register_ranges_a20x;
447 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
448 }
449
450
451 /* Write HW registers into shadow */
452 for (i = 0; i < (reg_array_size/2) ; i++) {
453 build_reg_to_mem_range(ptr_register_ranges[i*2],
454 ptr_register_ranges[i*2+1],
455 &cmd, drawctxt);
456 }
457 }
458
459 /* Copy ALU constants */
460 cmd =
461 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
462 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
463
464 /* Copy Tex constants */
465 cmd =
466 reg_to_mem(cmd,
467 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
468 REG_SQ_FETCH_0, TEX_CONSTANTS);
469#else
470
471 /* Insert a wait for idle packet before reading the registers.
472 * This is to fix a hang/reset seen during stress testing. In this
473 * hang, CP encountered a timeout reading SQ's boolean constant
474 * register. There is logic in the HW that blocks reading of this
475 * register when the SQ block is not idle, which we believe is
476 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600477 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600478 *cmd++ = 0;
479
480 /* H/w registers are already shadowed; just need to disable shadowing
481 * to prevent corruption.
482 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600483 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600484 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
485 *cmd++ = 4 << 16; /* regs, start=0 */
486 *cmd++ = 0x0; /* count = 0 */
487
488 /* ALU constants are already shadowed; just need to disable shadowing
489 * to prevent corruption.
490 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600491 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600492 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
493 *cmd++ = 0 << 16; /* ALU, start=0 */
494 *cmd++ = 0x0; /* count = 0 */
495
496 /* Tex constants are already shadowed; just need to disable shadowing
497 * to prevent corruption.
498 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600499 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600500 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
501 *cmd++ = 1 << 16; /* Tex, start=0 */
502 *cmd++ = 0x0; /* count = 0 */
503#endif
504
505 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600506 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600507 *cmd++ = REG_SQ_GPR_MANAGEMENT;
508 *cmd++ = tmp_ctx.reg_values[0];
509
Jordan Crouse084427d2011-07-28 08:37:58 -0600510 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600511 *cmd++ = REG_TP0_CHICKEN;
512 *cmd++ = tmp_ctx.reg_values[1];
513
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600514 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600515 unsigned int i;
516 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700517 for (i = REG_A220_VSC_BIN_SIZE; i <=
518 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600519 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600520 *cmd++ = i;
521 *cmd++ = tmp_ctx.reg_values[j];
522 j++;
523 }
524 }
525
526 /* Copy Boolean constants */
527 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
528 BOOL_CONSTANTS);
529
530 /* Copy Loop constants */
531 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
532 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
533
534 /* create indirect buffer command for above command sequence */
535 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
536
537 tmp_ctx.cmd = cmd;
538}
539
540/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
541static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
542 struct adreno_context *drawctxt,
543 struct gmem_shadow_t *shadow)
544{
545 unsigned int *cmds = shadow->gmem_save_commands;
546 unsigned int *start = cmds;
547 /* Calculate the new offset based on the adjusted base */
548 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
549 unsigned int addr = shadow->gmemshadow.gpuaddr;
550 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
551
552 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600553 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600554 *cmds++ = REG_TP0_CHICKEN;
555
556 *cmds++ = tmp_ctx.chicken_restore;
557
Jordan Crouse084427d2011-07-28 08:37:58 -0600558 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600559 *cmds++ = 0;
560
561 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600562 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600563 *cmds++ = 0x00000000;
564
565 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600566 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600567 *cmds++ = 0x00000000;
568
569 /* program shader */
570
571 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600572 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600573 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
574 *cmds++ = 0;
575 /* valid(?) vtx constant flag & addr */
576 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
577 /* limit = 12 dwords */
578 *cmds++ = 0x00000030;
579
580 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600581 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600582 *cmds++ = 0x1;
583
Jordan Crouse084427d2011-07-28 08:37:58 -0600584 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600585 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600586 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
587 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
588 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
589
Jordan Crouse084427d2011-07-28 08:37:58 -0600590 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600591 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600592 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
593
Jordan Crouse084427d2011-07-28 08:37:58 -0600594 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600595 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600596 *cmds++ = 0x00000c20;
597
Tarun Karra16346b02011-07-24 15:04:26 -0700598 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600599 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700600 *cmds++ = 0x180;
601
602 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600603 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700604 *cmds++ = 0x00003F00;
605
Jordan Crouse084427d2011-07-28 08:37:58 -0600606 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700607 *cmds++ = adreno_encode_istore_size(adreno_dev)
608 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700609
Jordan Crousea78c9172011-07-11 13:14:09 -0600610 /* load the patched vertex shader stream */
611 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
612
613 /* Load the patched fragment shader stream */
614 cmds =
615 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
616
617 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600618 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600619 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600620 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600621 *cmds++ = 0x10018001;
622 else
623 *cmds++ = 0x10010001;
624 *cmds++ = 0x00000008;
625
626 /* resolve */
627
628 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600629 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600630 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600631 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
632 *cmds++ = 0x00000b00;
633
634 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600635 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600636 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600637 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
638
639 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
640 * Base=gmem_base
641 */
642 /* gmem base assumed 4K aligned. */
643 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
644 *cmds++ =
645 (shadow->
646 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
647
648 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600649 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600650 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600651 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600652 *cmds++ = 0x08;
653 else
654 *cmds++ = 0;
655
656 /* set REG_PA_SU_SC_MODE_CNTL
657 * Front_ptype = draw triangles
658 * Back_ptype = draw triangles
659 * Provoking vertex = last
660 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600661 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600662 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600663 *cmds++ = 0x00080240;
664
665 /* Use maximum scissor values -- quad vertices already have the
666 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600667 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600668 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600669 *cmds++ = (0 << 16) | 0;
670 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600671 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600672 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600673 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
674 *cmds++ = (0x1fff << 16) | (0x1fff);
675
676 /* load the viewport so that z scale = clear depth and
677 * z offset = 0.0f
678 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600679 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600680 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600681 *cmds++ = 0xbf800000; /* -1.0f */
682 *cmds++ = 0x0;
683
Jordan Crouse084427d2011-07-28 08:37:58 -0600684 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600685 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600686 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
687
Jordan Crouse084427d2011-07-28 08:37:58 -0600688 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600689 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600690 *cmds++ = 0xffffffff;
691
Jordan Crouse084427d2011-07-28 08:37:58 -0600692 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600693 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600694 *cmds++ = 0x00000000;
695 *cmds++ = 0x00000000;
696
697 /* load the stencil ref value
698 * $AAM - do this later
699 */
700
701 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600702 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600703 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600704 *cmds++ = 0; /* RB_COPY_CONTROL */
705 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
706 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
707
708 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
709 * MaskWrite:R=G=B=A=1
710 */
711 *cmds++ = 0x0003c008 |
712 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
713 /* Make sure we stay in offsetx field. */
714 BUG_ON(offset & 0xfffff000);
715 *cmds++ = offset;
716
Jordan Crouse084427d2011-07-28 08:37:58 -0600717 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600718 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600719 *cmds++ = 0x6; /* EDRAM copy */
720
Jordan Crouse084427d2011-07-28 08:37:58 -0600721 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600722 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600723 *cmds++ = 0x00010000;
724
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600725 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600726 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600727 *cmds++ = 0;
728
Jordan Crouse084427d2011-07-28 08:37:58 -0600729 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700730 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600731 *cmds++ = 0x0000000;
732
Jordan Crouse084427d2011-07-28 08:37:58 -0600733 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600734 *cmds++ = 0; /* viz query info. */
735 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
736 *cmds++ = 0x00004088;
737 *cmds++ = 3; /* NumIndices=3 */
738 } else {
739 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600740 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600741 *cmds++ = 0; /* viz query info. */
742 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
743 *cmds++ = 0x00030088;
744 }
745
746 /* create indirect buffer command for above command sequence */
747 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
748
749 return cmds;
750}
751
752/* context restore */
753
754/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
755static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
756 struct adreno_context *drawctxt,
757 struct gmem_shadow_t *shadow)
758{
759 unsigned int *cmds = shadow->gmem_restore_commands;
760 unsigned int *start = cmds;
761
762 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600763 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600764 *cmds++ = REG_TP0_CHICKEN;
765 *cmds++ = tmp_ctx.chicken_restore;
766
Jordan Crouse084427d2011-07-28 08:37:58 -0600767 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600768 *cmds++ = 0;
769
770 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600771 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600772 *cmds++ = 0x00000000;
773
774 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600775 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600776 *cmds++ = 0x00000000;
777 /* shader constants */
778
779 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600780 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600781
782 *cmds++ = (0x1 << 16) | (9 * 6);
783 /* valid(?) vtx constant flag & addr */
784 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
785 /* limit = 12 dwords */
786 *cmds++ = 0x00000030;
787 /* valid(?) vtx constant flag & addr */
788 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
789 /* limit = 8 dwords */
790 *cmds++ = 0x00000020;
791 *cmds++ = 0;
792 *cmds++ = 0;
793
794 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600795 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600796 *cmds++ = 0x1;
797
798 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
799
Tarun Karra16346b02011-07-24 15:04:26 -0700800 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600801 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700802 *cmds++ = 0x180;
803
804 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600805 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700806 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
807
Jordan Crouse084427d2011-07-28 08:37:58 -0600808 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700809 *cmds++ = adreno_encode_istore_size(adreno_dev)
810 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700811
Jordan Crousea78c9172011-07-11 13:14:09 -0600812 /* Load the patched fragment shader stream */
813 cmds =
814 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
815
816 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600817 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600818 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600819 *cmds++ = 0x10030002;
820 *cmds++ = 0x00000008;
821
Jordan Crouse084427d2011-07-28 08:37:58 -0600822 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600823 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600824 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
825
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600826 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600827 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600828 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600829 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600830 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
831 }
832
833 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600834 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600835 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600836 *cmds++ = 0x00000c20;
837
Jordan Crouse084427d2011-07-28 08:37:58 -0600838 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600839 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600840 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
841 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
842 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
843
Jordan Crouse084427d2011-07-28 08:37:58 -0600844 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600845 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600846 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
847 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
848
Jordan Crouse084427d2011-07-28 08:37:58 -0600849 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600850 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600851 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
852
Jordan Crouse084427d2011-07-28 08:37:58 -0600853 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600854 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600855 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
856
857 /* set REG_PA_SU_SC_MODE_CNTL
858 * Front_ptype = draw triangles
859 * Back_ptype = draw triangles
860 * Provoking vertex = last
861 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600862 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600863 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600864 *cmds++ = 0x00080240;
865
866 /* texture constants */
867 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600868 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600869 *cmds++ = (0x1 << 16) | (0 * 6);
870 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
871 cmds[0] |= (shadow->pitch >> 5) << 22;
872 cmds[1] |=
873 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
874 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
875 cmds += SYS2GMEM_TEX_CONST_LEN;
876
877 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600878 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600879 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600880 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
881
882 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
883 * Base=gmem_base
884 */
885 *cmds++ =
886 (shadow->
887 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
888
889 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600890 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600891 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600892
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600893 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600894 *cmds++ = 8; /* disable Z */
895 else
896 *cmds++ = 0; /* disable Z */
897
898 /* Use maximum scissor values -- quad vertices already
899 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600900 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600901 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600902 *cmds++ = (0 << 16) | 0;
903 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600904 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600905 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600906 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
907 *cmds++ = ((0x1fff) << 16) | 0x1fff;
908
Jordan Crouse084427d2011-07-28 08:37:58 -0600909 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600910 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600911 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
912 *cmds++ = 0x00000b00;
913
914 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600915 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600916 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600917 *cmds++ = 0xbf800000;
918 *cmds++ = 0x0;
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_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600922 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
923
Jordan Crouse084427d2011-07-28 08:37:58 -0600924 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600925 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600926 *cmds++ = 0xffffffff;
927
Jordan Crouse084427d2011-07-28 08:37:58 -0600928 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600929 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600930 *cmds++ = 0x00000000;
931 *cmds++ = 0x00000000;
932
933 /* load the stencil ref value
934 * $AAM - do this later
935 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600936 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600937 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600938 /* draw pixels with color and depth/stencil component */
939 *cmds++ = 0x4;
940
Jordan Crouse084427d2011-07-28 08:37:58 -0600941 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600942 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600943 *cmds++ = 0x00010000;
944
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600945 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600946 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600947 *cmds++ = 0;
948
Jordan Crouse084427d2011-07-28 08:37:58 -0600949 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700950 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600951 *cmds++ = 0x0000000;
952
Jordan Crouse084427d2011-07-28 08:37:58 -0600953 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600954 *cmds++ = 0; /* viz query info. */
955 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
956 *cmds++ = 0x00004088;
957 *cmds++ = 3; /* NumIndices=3 */
958 } else {
959 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600960 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600961 *cmds++ = 0; /* viz query info. */
962 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
963 *cmds++ = 0x00030088;
964 }
965
966 /* create indirect buffer command for above command sequence */
967 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
968
969 return cmds;
970}
971
Jordan Crousea78c9172011-07-11 13:14:09 -0600972static void build_regrestore_cmds(struct adreno_device *adreno_dev,
973 struct adreno_context *drawctxt)
974{
975 unsigned int *start = tmp_ctx.cmd;
976 unsigned int *cmd = start;
977
978 unsigned int i = 0;
979 unsigned int reg_array_size = 0;
980 const unsigned int *ptr_register_ranges;
981
Jordan Crouse084427d2011-07-28 08:37:58 -0600982 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600983 *cmd++ = 0;
984
985 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -0600986 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -0600987 cmd++;
988#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
989 /* Force mismatch */
990 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
991#else
992 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
993#endif
994
995 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700996 if (adreno_is_a220(adreno_dev)) {
997 ptr_register_ranges = register_ranges_a220;
998 reg_array_size = ARRAY_SIZE(register_ranges_a220);
999 } else if (adreno_is_a225(adreno_dev)) {
1000 ptr_register_ranges = register_ranges_a225;
1001 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001002 } else {
1003 ptr_register_ranges = register_ranges_a20x;
1004 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1005 }
1006
1007
1008 for (i = 0; i < (reg_array_size/2); i++) {
1009 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1010 ptr_register_ranges[i*2+1]);
1011 }
1012
1013 /* Now we know how many register blocks we have, we can compute command
1014 * length
1015 */
1016 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001017 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001018 /* Enable shadowing for the entire register block. */
1019#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1020 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1021#else
1022 start[4] |= (1 << 24) | (4 << 16);
1023#endif
1024
1025 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001026 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001027 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1028 *cmd++ = 0x00040400;
1029
Jordan Crouse084427d2011-07-28 08:37:58 -06001030 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001031 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001032 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001033 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1034 *cmd++ = 0x00000000;
1035
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001036 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001037 unsigned int i;
1038 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001039 for (i = REG_A220_VSC_BIN_SIZE; i <=
1040 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001041 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001042 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1043 &drawctxt->gpustate);
1044 *cmd++ = 0x00000000;
1045 j++;
1046 }
1047 }
1048
1049 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001050 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001051 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1052#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1053 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1054#else
1055 *cmd++ = (1 << 24) | (0 << 16) | 0;
1056#endif
1057 *cmd++ = ALU_CONSTANTS;
1058
1059 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001060 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001061 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1062#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1063 /* Disable shadowing */
1064 *cmd++ = (0 << 24) | (1 << 16) | 0;
1065#else
1066 *cmd++ = (1 << 24) | (1 << 16) | 0;
1067#endif
1068 *cmd++ = TEX_CONSTANTS;
1069
1070 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001071 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001072 *cmd++ = (2 << 16) | 0;
1073
1074 /* the next BOOL_CONSTANT dwords is the shadow area for
1075 * boolean constants.
1076 */
1077 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1078 cmd += BOOL_CONSTANTS;
1079
1080 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001081 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001082 *cmd++ = (3 << 16) | 0;
1083
1084 /* the next LOOP_CONSTANTS dwords is the shadow area for
1085 * loop constants.
1086 */
1087 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1088 cmd += LOOP_CONSTANTS;
1089
1090 /* create indirect buffer command for above command sequence */
1091 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1092
1093 tmp_ctx.cmd = cmd;
1094}
1095
Jordan Crousea78c9172011-07-11 13:14:09 -06001096static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001097build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1098 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001099{
1100 unsigned int *cmd = tmp_ctx.cmd;
1101 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001102 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001103 unsigned int *partition1;
1104 unsigned int *shaderBases, *partition2;
1105
Jordan Crousea78c9172011-07-11 13:14:09 -06001106 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1107 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001108 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1109 + _shader_shadow_size(adreno_dev);
1110 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1111 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001112
1113 /* restore shader partitioning and instructions */
1114
1115 restore = cmd; /* start address */
1116
1117 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001118 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001119 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1120
1121 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001122 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001123 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1124
1125 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001126 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001127 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1128
Jordan Crousea78c9172011-07-11 13:14:09 -06001129 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001130 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001131 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1132 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1133
1134 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001135 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001136 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1137 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1138
1139 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001140 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001141 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1142 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001143
1144 /* create indirect buffer command for above command sequence */
1145 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1146
1147 /*
1148 * fixup SET_SHADER_BASES data
1149 *
1150 * since self-modifying PM4 code is being used here, a seperate
1151 * command buffer is used for this fixup operation, to ensure the
1152 * commands are not read by the PM4 engine before the data fields
1153 * have been written.
1154 */
1155
1156 fixup = cmd; /* start address */
1157
1158 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001159 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001160 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1161
1162 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001163 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001164 *cmd++ = REG_SCRATCH_REG2;
1165 /* AND off invalid bits. */
1166 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001167 /* OR in instruction memory size. */
1168 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001169
1170 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001171 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001172 *cmd++ = REG_SCRATCH_REG2;
1173 /* TBD #5: shader bases (to restore) */
1174 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1175
1176 /* create indirect buffer command for above command sequence */
1177 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1178
1179 /* save shader partitioning and instructions */
1180
1181 save = cmd; /* start address */
1182
Jordan Crouse084427d2011-07-28 08:37:58 -06001183 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001184 *cmd++ = 0;
1185
1186 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1187 * store the value in the data fields of the SET_CONSTANT commands
1188 * above.
1189 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001190 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001191 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1192 /* TBD #4a: partition info (to restore) */
1193 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001194 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001195 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1196 /* TBD #4b: partition info (to fixup) */
1197 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1198
Jordan Crousea78c9172011-07-11 13:14:09 -06001199
1200 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001201 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001202 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1203 /* TBD #1: start/size (to restore) */
1204 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1205
1206 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001207 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001208 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1209 /* TBD #2: start/size (to restore) */
1210 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1211
1212 /* store the shared shader instructions if vertex base is nonzero */
1213
Jordan Crouse084427d2011-07-28 08:37:58 -06001214 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001215 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1216 /* TBD #3: start/size (to restore) */
1217 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1218
Jordan Crousea78c9172011-07-11 13:14:09 -06001219
Jordan Crouse084427d2011-07-28 08:37:58 -06001220 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001221 *cmd++ = 0;
1222
1223 /* create indirect buffer command for above command sequence */
1224 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1225
1226 tmp_ctx.cmd = cmd;
1227}
1228
1229/* create buffers for saving/restoring registers, constants, & GMEM */
1230static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1231 struct adreno_context *drawctxt)
1232{
1233 int result;
1234
1235 /* Allocate vmalloc memory to store the gpustate */
1236 result = kgsl_allocate(&drawctxt->gpustate,
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001237 drawctxt->pagetable, _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001238
1239 if (result)
1240 return result;
1241
1242 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1243
1244 /* Blank out h/w register, constant, and command buffer shadows. */
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001245 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1246 _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001247
1248 /* set-up command and vertex buffer pointers */
1249 tmp_ctx.cmd = tmp_ctx.start
1250 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1251
1252 /* build indirect command buffers to save & restore regs/constants */
1253 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1254 build_regrestore_cmds(adreno_dev, drawctxt);
1255 build_regsave_cmds(adreno_dev, drawctxt);
1256
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001257 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001258
1259 kgsl_cache_range_op(&drawctxt->gpustate,
1260 KGSL_CACHE_OP_FLUSH);
1261
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001262 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1263 drawctxt->gpustate.gpuaddr,
1264 drawctxt->gpustate.size, false);
Jordan Crousea78c9172011-07-11 13:14:09 -06001265 return 0;
1266}
1267
1268/* create buffers for saving/restoring registers, constants, & GMEM */
1269static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1270 struct adreno_context *drawctxt)
1271{
1272 int result;
1273
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001274 calc_gmemsize(&drawctxt->context_gmem_shadow,
1275 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001276 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1277
1278 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1279 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1280
1281 if (result)
1282 return result;
1283
1284 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1285 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1286
1287 /* blank out gmem shadow. */
1288 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1289 drawctxt->context_gmem_shadow.size);
1290
1291 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001292 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1293 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001294
1295 /* build TP0_CHICKEN register restore command buffer */
1296 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1297
1298 /* build indirect command buffers to save & restore gmem */
1299 /* Idle because we are reading PM override registers */
1300 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1301 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1302 tmp_ctx.cmd =
1303 build_gmem2sys_cmds(adreno_dev, drawctxt,
1304 &drawctxt->context_gmem_shadow);
1305 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1306 tmp_ctx.cmd =
1307 build_sys2gmem_cmds(adreno_dev, drawctxt,
1308 &drawctxt->context_gmem_shadow);
1309
1310 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1311 KGSL_CACHE_OP_FLUSH);
1312
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001313 kgsl_cffdump_syncmem(NULL,
1314 &drawctxt->context_gmem_shadow.gmemshadow,
1315 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1316 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1317
Jordan Crousea78c9172011-07-11 13:14:09 -06001318 return 0;
1319}
1320
1321static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1322 struct adreno_context *context)
1323{
1324 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001325 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001326
1327 if (context == NULL)
1328 return;
1329
1330 if (context->flags & CTXT_FLAGS_GPU_HANG)
1331 KGSL_CTXT_WARN(device,
1332 "Current active context has caused gpu hang\n");
1333
1334 KGSL_CTXT_INFO(device,
1335 "active context flags %08x\n", context->flags);
1336
1337 /* save registers and constants. */
1338 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1339
1340 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1341 /* save shader partitioning and instructions. */
1342 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1343 context->shader_save, 3);
1344
1345 /* fixup shader partitioning parameter for
1346 * SET_SHADER_BASES.
1347 */
1348 adreno_ringbuffer_issuecmds(device, 0,
1349 context->shader_fixup, 3);
1350
1351 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1352 }
1353
1354 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1355 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1356 /* save gmem.
1357 * (note: changes shader. shader must already be saved.)
1358 */
1359 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1360 context->context_gmem_shadow.gmem_save, 3);
1361
1362 /* Restore TP0_CHICKEN */
1363 adreno_ringbuffer_issuecmds(device, 0,
1364 context->chicken_restore, 3);
1365
1366 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001367 } else if (adreno_is_a225(adreno_dev)) {
1368 unsigned int *cmds = &cmd[0];
1369 /*
1370 * Issue an empty draw call to avoid possible hangs due to
1371 * repeated idles without intervening draw calls.
1372 * On adreno 225 the PC block has a cache that is only
1373 * flushed on draw calls and repeated idles can make it
1374 * overflow. The gmem save path contains draw calls so
1375 * this workaround isn't needed there.
1376 */
1377 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1378 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1379 *cmds++ = 0;
1380 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1381 *cmds++ = 0;
1382 *cmds++ = 1<<14;
1383 *cmds++ = 0;
1384 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1385 *cmds++ = 0;
1386 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1387 *cmds++ = 0x00000000;
1388
1389 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1390 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001391 }
1392}
1393
1394static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1395 struct adreno_context *context)
1396{
1397 struct kgsl_device *device = &adreno_dev->dev;
1398 unsigned int cmds[5];
1399
1400 if (context == NULL) {
1401 /* No context - set the default apgetable and thats it */
1402 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1403 return;
1404 }
1405
1406 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1407
Jordan Crouse084427d2011-07-28 08:37:58 -06001408 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001409 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001410 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001411 cmds[3] = device->memstore.gpuaddr +
1412 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1413 cmds[4] = (unsigned int) context;
1414 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1415 kgsl_mmu_setstate(device, context->pagetable);
1416
1417#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1418 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1419 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1420 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1421#endif
1422
1423 /* restore gmem.
1424 * (note: changes shader. shader must not already be restored.)
1425 */
1426 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1427 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1428 context->context_gmem_shadow.gmem_restore, 3);
1429
1430 /* Restore TP0_CHICKEN */
1431 adreno_ringbuffer_issuecmds(device, 0,
1432 context->chicken_restore, 3);
1433
1434 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1435 }
1436
1437 /* restore registers and constants. */
1438 adreno_ringbuffer_issuecmds(device, 0,
1439 context->reg_restore, 3);
1440
1441 /* restore shader instructions & partitioning. */
1442 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1443 adreno_ringbuffer_issuecmds(device, 0,
1444 context->shader_restore, 3);
1445 }
1446
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001447 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001448 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001449 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001450 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001451 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001452}
1453
1454/*
1455 * Interrupt management
1456 *
1457 * a2xx interrupt control is distributed among the various
1458 * hardware components (RB, CP, MMU). The main interrupt
1459 * tells us which component fired the interrupt, but one needs
1460 * to go to the individual component to find out why. The
1461 * following functions provide the broken out support for
1462 * managing the interrupts
1463 */
1464
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001465#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001466
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001467#define CP_INT_MASK \
1468 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001469 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1470 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1471 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1472 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001473 CP_INT_CNTL__IB1_INT_MASK | \
1474 CP_INT_CNTL__RB_INT_MASK)
1475
1476#define VALID_STATUS_COUNT_MAX 10
1477
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001478static struct {
1479 unsigned int mask;
1480 const char *message;
1481} kgsl_cp_error_irqs[] = {
1482 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1483 "ringbuffer TO packet in IB interrupt" },
1484 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1485 "ringbuffer opcode error interrupt" },
1486 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1487 "ringbuffer protected mode error interrupt" },
1488 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1489 "ringbuffer reserved bit error interrupt" },
1490 { CP_INT_CNTL__IB_ERROR_MASK,
1491 "ringbuffer IB error interrupt" },
1492};
1493
Jordan Crousea78c9172011-07-11 13:14:09 -06001494static void a2xx_cp_intrcallback(struct kgsl_device *device)
1495{
1496 unsigned int status = 0, num_reads = 0, master_status = 0;
1497 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1498 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001499 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001500
1501 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1502 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1503 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1504 adreno_regread(device, REG_CP_INT_STATUS, &status);
1505 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1506 &master_status);
1507 num_reads++;
1508 }
1509 if (num_reads > 1)
1510 KGSL_DRV_WARN(device,
1511 "Looped %d times to read REG_CP_INT_STATUS\n",
1512 num_reads);
1513 if (!status) {
1514 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1515 /* This indicates that we could not read CP_INT_STAT.
1516 * As a precaution just wake up processes so
1517 * they can check their timestamps. Since, we
1518 * did not ack any interrupts this interrupt will
1519 * be generated again */
1520 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1521 wake_up_interruptible_all(&device->wait_queue);
1522 } else
1523 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1524 return;
1525 }
1526
1527 if (status & CP_INT_CNTL__RB_INT_MASK) {
1528 /* signal intr completion event */
1529 unsigned int enableflag = 0;
1530 kgsl_sharedmem_writel(&rb->device->memstore,
1531 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1532 enableflag);
1533 wmb();
1534 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1535 }
1536
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001537 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1538 if (status & kgsl_cp_error_irqs[i].mask) {
1539 KGSL_CMD_CRIT(rb->device, "%s\n",
1540 kgsl_cp_error_irqs[i].message);
1541 /*
1542 * on fatal errors, turn off the interrupts to
1543 * avoid storming. This has the side effect of
1544 * forcing a PM dump when the timestamp times out
1545 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001546
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001547 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1548 }
1549 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001550
1551 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001552 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001553 adreno_regwrite(device, REG_CP_INT_ACK, status);
1554
1555 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1556 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001557 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001558 wake_up_interruptible_all(&device->wait_queue);
1559 atomic_notifier_call_chain(&(device->ts_notifier_list),
1560 device->id,
1561 NULL);
1562 }
1563}
1564
1565static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1566{
1567 unsigned int status = 0;
1568 unsigned int rderr = 0;
1569
1570 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1571
1572 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1573 union rbbm_read_error_u rerr;
1574 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1575 rerr.val = rderr;
1576 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1577 rerr.f.read_error &&
1578 rerr.f.read_requester)
1579 KGSL_DRV_WARN(device,
1580 "rbbm read error interrupt: %08x\n", rderr);
1581 else
1582 KGSL_DRV_CRIT(device,
1583 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001584 }
1585
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001586 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001587 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1588}
1589
1590irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1591{
1592 struct kgsl_device *device = &adreno_dev->dev;
1593 irqreturn_t result = IRQ_NONE;
1594 unsigned int status;
1595
1596 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1597
1598 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1599 kgsl_mh_intrcallback(device);
1600 result = IRQ_HANDLED;
1601 }
1602
1603 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1604 a2xx_cp_intrcallback(device);
1605 result = IRQ_HANDLED;
1606 }
1607
1608 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1609 a2xx_rbbm_intrcallback(device);
1610 result = IRQ_HANDLED;
1611 }
1612
1613 return result;
1614}
1615
1616static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1617{
1618 struct kgsl_device *device = &adreno_dev->dev;
1619
1620 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001621 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1622 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001623 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1624 } else {
1625 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1626 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1627 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1628 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001629
1630 /* Force the writes to post before touching the IRQ line */
1631 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001632}
1633
1634struct adreno_gpudev adreno_a2xx_gpudev = {
1635 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1636 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1637 .ctxt_save = a2xx_ctxt_save,
1638 .ctxt_restore = a2xx_ctxt_restore,
1639 .irq_handler = a2xx_irq_handler,
1640 .irq_control = a2xx_irq_control,
1641};