blob: d083586535efa1dcce3ddeb5b7aeac05ae3bad6c [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"
Norman Geed7402ff2011-10-28 08:51:11 -060018#include "adreno_a2xx_trace.h"
Jordan Crousea78c9172011-07-11 13:14:09 -060019
20/*
21 *
22 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
23 * (34.5KB)
24 *
25 * +---------------------+------------+-------------+---+---------------------+
26 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
27 * +---------------------+------------+-------------+---+---------------------+
28 * ________________________________/ \____________________
29 * / |
30 * +--------------+-----------+------+-----------+------------------------+
31 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
32 * +--------------+-----------+------+-----------+------------------------+
33 *
34 * 8K - ALU Constant Shadow (8K aligned)
35 * 4K - H/W Register Shadow (8K aligned)
36 * 4K - Command and Vertex Buffers
37 * - Indirect command buffer : Const/Reg restore
38 * - includes Loop & Bool const shadows
39 * - Indirect command buffer : Const/Reg save
40 * - Quad vertices & texture coordinates
41 * - Indirect command buffer : Gmem save
42 * - Indirect command buffer : Gmem restore
43 * - Unused (padding to 8KB boundary)
44 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
45 * 18K - Shader Instruction Shadow
46 * - 6K vertex (32 byte aligned)
47 * - 6K pixel (32 byte aligned)
48 * - 6K shared (32 byte aligned)
49 *
50 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
51 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
52 * 16 bytes per constant. If the texture constants were transfered this way,
53 * the Command & Vertex Buffers section would extend past the 16K boundary.
54 * By moving the texture constant shadow area to start at 16KB boundary, we
55 * only require approximately 40 bytes more memory, but are able to use the
56 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
57 * context switching.
58 *
59 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
60 * constants would require an additional 8KB each, for alignment.]
61 *
62 */
63
64/* Constants */
65
66#define ALU_CONSTANTS 2048 /* DWORDS */
67#define NUM_REGISTERS 1024 /* DWORDS */
68#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
69#define CMD_BUFFER_LEN 9216 /* DWORDS */
70#else
71#define CMD_BUFFER_LEN 3072 /* DWORDS */
72#endif
73#define TEX_CONSTANTS (32*6) /* DWORDS */
74#define BOOL_CONSTANTS 8 /* DWORDS */
75#define LOOP_CONSTANTS 56 /* DWORDS */
Jordan Crousea78c9172011-07-11 13:14:09 -060076
77/* LOAD_CONSTANT_CONTEXT shadow size */
78#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
79
80#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
81#define REG_SHADOW_SIZE 0x1000 /* 4KB */
82#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
83#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
84#else
85#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
86#endif
87#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
Jordan Crousea78c9172011-07-11 13:14:09 -060088
89#define REG_OFFSET LCC_SHADOW_SIZE
90#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
91#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
92#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
93
Jeremy Gebbenddf6b572011-09-09 13:39:49 -070094static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
95{
96 return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
97}
98
99static inline int _context_size(struct adreno_device *adreno_dev)
100{
101 return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
102}
Jordan Crousea78c9172011-07-11 13:14:09 -0600103
104/* A scratchpad used to build commands during context create */
105
106static struct tmp_ctx {
107 unsigned int *start; /* Command & Vertex buffer start */
108 unsigned int *cmd; /* Next available dword in C&V buffer */
109
110 /* address of buffers, needed when creating IB1 command buffers. */
111 uint32_t bool_shadow; /* bool constants */
112 uint32_t loop_shadow; /* loop constants */
113
Jordan Crousea78c9172011-07-11 13:14:09 -0600114 uint32_t shader_shared; /* shared shader instruction shadow */
115 uint32_t shader_vertex; /* vertex shader instruction shadow */
116 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600117
118 /* Addresses in command buffer where separately handled registers
119 * are saved
120 */
121 uint32_t reg_values[33];
122 uint32_t chicken_restore;
123
124 uint32_t gmem_base; /* Base gpu address of GMEM */
125
126} tmp_ctx;
127
128/* context save (gmem -> sys) */
129
130/* pre-compiled vertex shader program
131*
132* attribute vec4 P;
133* void main(void)
134* {
135* gl_Position = P;
136* }
137*/
138#define GMEM2SYS_VTX_PGM_LEN 0x12
139
140static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
141 0x00011003, 0x00001000, 0xc2000000,
142 0x00001004, 0x00001000, 0xc4000000,
143 0x00001005, 0x00002000, 0x00000000,
144 0x1cb81000, 0x00398a88, 0x00000003,
145 0x140f803e, 0x00000000, 0xe2010100,
146 0x14000000, 0x00000000, 0xe2000000
147};
148
149/* pre-compiled fragment shader program
150*
151* precision highp float;
152* uniform vec4 clear_color;
153* void main(void)
154* {
155* gl_FragColor = clear_color;
156* }
157*/
158
159#define GMEM2SYS_FRAG_PGM_LEN 0x0c
160
161static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
162 0x00000000, 0x1002c400, 0x10000000,
163 0x00001003, 0x00002000, 0x00000000,
164 0x140f8000, 0x00000000, 0x22000000,
165 0x14000000, 0x00000000, 0xe2000000
166};
167
168/* context restore (sys -> gmem) */
169/* pre-compiled vertex shader program
170*
171* attribute vec4 position;
172* attribute vec4 texcoord;
173* varying vec4 texcoord0;
174* void main()
175* {
176* gl_Position = position;
177* texcoord0 = texcoord;
178* }
179*/
180
181#define SYS2GMEM_VTX_PGM_LEN 0x18
182
183static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
184 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
185 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
186 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
187 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
188 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
189 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
190};
191
192/* pre-compiled fragment shader program
193*
194* precision mediump float;
195* uniform sampler2D tex0;
196* varying vec4 texcoord0;
197* void main()
198* {
199* gl_FragColor = texture2D(tex0, texcoord0.xy);
200* }
201*/
202
203#define SYS2GMEM_FRAG_PGM_LEN 0x0f
204
205static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
206 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
207 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
208 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
209 0x14000000, 0x00000000, 0xe2000000
210};
211
212/* shader texture constants (sysmem -> gmem) */
213#define SYS2GMEM_TEX_CONST_LEN 6
214
215static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
216 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
217 * RFMode=ZeroClamp-1, Dim=1:2d
218 */
219 0x00000002, /* Pitch = TBD */
220
221 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
222 * NearestClamp=1:OGL Mode
223 */
224 0x00000800, /* Address[31:12] = TBD */
225
226 /* Width, Height, EndianSwap=0:None */
227 0, /* Width & Height = TBD */
228
229 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
230 * Mip=2:BaseMap
231 */
232 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
233
234 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
235 * Dim3d=0
236 */
237 0,
238
239 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
240 * Dim=1:2d, MipPacking=0
241 */
242 1 << 9 /* Mip Address[31:12] = TBD */
243};
244
Jordan Crousea78c9172011-07-11 13:14:09 -0600245#define NUM_COLOR_FORMATS 13
246
247static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
248 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
249 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
250 FMT_5_6_5, /* COLORX_5_6_5 */
251 FMT_8, /* COLORX_8 */
252 FMT_8_8, /* COLORX_8_8 */
253 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
254 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
255 FMT_16_FLOAT, /* COLORX_16_FLOAT */
256 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
257 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
258 FMT_32_FLOAT, /* COLORX_32_FLOAT */
259 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
260 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
261};
262
263static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
264 2, /* COLORX_4_4_4_4 */
265 2, /* COLORX_1_5_5_5 */
266 2, /* COLORX_5_6_5 */
267 1, /* COLORX_8 */
268 2, /* COLORX_8_8 8*/
269 4, /* COLORX_8_8_8_8 */
270 4, /* COLORX_S8_8_8_8 */
271 2, /* COLORX_16_FLOAT */
272 4, /* COLORX_16_16_FLOAT */
273 8, /* COLORX_16_16_16_16_FLOAT */
274 4, /* COLORX_32_FLOAT */
275 8, /* COLORX_32_32_FLOAT */
276 16, /* COLORX_32_32_32_32_FLOAT */
277};
278
279/* shader linkage info */
280#define SHADER_CONST_ADDR (11 * 6 + 3)
281
Jordan Crousea78c9172011-07-11 13:14:09 -0600282
283static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
284 unsigned int *shader_pgm, int dwords)
285{
286 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600287 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600288 /* 0=vertex shader, 1=fragment shader */
289 *cmds++ = vtxfrag;
290 /* instruction start & size (in 32-bit words) */
291 *cmds++ = ((0 << 16) | dwords);
292
293 memcpy(cmds, shader_pgm, dwords << 2);
294 cmds += dwords;
295
296 return cmds;
297}
298
299static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
300 uint32_t src, int dwords)
301{
302 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600303 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600304 *cmds++ = src++;
305 *cmds++ = dst;
306 dst += 4;
307 }
308
309 return cmds;
310}
311
312#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
313
314static void build_reg_to_mem_range(unsigned int start, unsigned int end,
315 unsigned int **cmd,
316 struct adreno_context *drawctxt)
317{
318 unsigned int i = start;
319
320 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600321 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600322 *(*cmd)++ = i;
323 *(*cmd)++ =
324 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
325 (i - 0x2000) * 4;
326 }
327}
328
329#endif
330
331/* chicken restore */
332static unsigned int *build_chicken_restore_cmds(
333 struct adreno_context *drawctxt)
334{
335 unsigned int *start = tmp_ctx.cmd;
336 unsigned int *cmds = start;
337
Jordan Crouse084427d2011-07-28 08:37:58 -0600338 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600339 *cmds++ = 0;
340
Jordan Crouse084427d2011-07-28 08:37:58 -0600341 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600342 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
343 *cmds++ = 0x00000000;
344
345 /* create indirect buffer command for above command sequence */
346 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
347
348 return cmds;
349}
350
351/****************************************************************************/
352/* context save */
353/****************************************************************************/
354
355static const unsigned int register_ranges_a20x[] = {
356 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
357 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
358 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
359 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
360 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
361 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
362 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
363 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
364 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
365 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
366 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
367 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
368 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
369 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
370};
371
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700372static const unsigned int register_ranges_a220[] = {
Jordan Crousea78c9172011-07-11 13:14:09 -0600373 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
374 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
375 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
376 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
377 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
378 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
379 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
380 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
381 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700382 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600383 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
384 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
385 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
386 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
387 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700388 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
389 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600390 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
391};
392
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700393static const unsigned int register_ranges_a225[] = {
394 REG_RB_SURFACE_INFO, REG_A225_RB_COLOR_INFO3,
395 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
396 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
397 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
398 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
399 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
400 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
401 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
402 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
403 REG_A220_PC_MAX_VTX_INDX, REG_A225_PC_MULTI_PRIM_IB_RESET_INDX,
404 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
405 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
406 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
407 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
408 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
409 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
410 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
411 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
Jeremy Gebbene139a042011-11-17 16:20:41 -0700412 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
413 REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700414};
415
Jordan Crousea78c9172011-07-11 13:14:09 -0600416
417/* save h/w regs, alu constants, texture contants, etc. ...
418* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
419*/
420static void build_regsave_cmds(struct adreno_device *adreno_dev,
421 struct adreno_context *drawctxt)
422{
423 unsigned int *start = tmp_ctx.cmd;
424 unsigned int *cmd = start;
425
Jordan Crouse084427d2011-07-28 08:37:58 -0600426 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600427 *cmd++ = 0;
428
429#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
430 /* Make sure the HW context has the correct register values
431 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600432 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600433 *cmd++ = 0;
434
435 {
436 unsigned int i = 0;
437 unsigned int reg_array_size = 0;
438 const unsigned int *ptr_register_ranges;
439
440 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700441 if (adreno_is_a220(adreno_dev)) {
442 ptr_register_ranges = register_ranges_a220;
443 reg_array_size = ARRAY_SIZE(register_ranges_a220);
444 } else if (adreno_is_a225(adreno_dev)) {
445 ptr_register_ranges = register_ranges_a225;
446 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600447 } else {
448 ptr_register_ranges = register_ranges_a20x;
449 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
450 }
451
452
453 /* Write HW registers into shadow */
454 for (i = 0; i < (reg_array_size/2) ; i++) {
455 build_reg_to_mem_range(ptr_register_ranges[i*2],
456 ptr_register_ranges[i*2+1],
457 &cmd, drawctxt);
458 }
459 }
460
461 /* Copy ALU constants */
462 cmd =
463 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
464 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
465
466 /* Copy Tex constants */
467 cmd =
468 reg_to_mem(cmd,
469 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
470 REG_SQ_FETCH_0, TEX_CONSTANTS);
471#else
472
473 /* Insert a wait for idle packet before reading the registers.
474 * This is to fix a hang/reset seen during stress testing. In this
475 * hang, CP encountered a timeout reading SQ's boolean constant
476 * register. There is logic in the HW that blocks reading of this
477 * register when the SQ block is not idle, which we believe is
478 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600479 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600480 *cmd++ = 0;
481
482 /* H/w registers are already shadowed; just need to disable shadowing
483 * to prevent corruption.
484 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600485 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600486 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
487 *cmd++ = 4 << 16; /* regs, start=0 */
488 *cmd++ = 0x0; /* count = 0 */
489
490 /* ALU constants are already shadowed; just need to disable shadowing
491 * to prevent corruption.
492 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600493 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600494 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
495 *cmd++ = 0 << 16; /* ALU, start=0 */
496 *cmd++ = 0x0; /* count = 0 */
497
498 /* Tex constants are already shadowed; just need to disable shadowing
499 * to prevent corruption.
500 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600501 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600502 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
503 *cmd++ = 1 << 16; /* Tex, start=0 */
504 *cmd++ = 0x0; /* count = 0 */
505#endif
506
507 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600508 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600509 *cmd++ = REG_SQ_GPR_MANAGEMENT;
510 *cmd++ = tmp_ctx.reg_values[0];
511
Jordan Crouse084427d2011-07-28 08:37:58 -0600512 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600513 *cmd++ = REG_TP0_CHICKEN;
514 *cmd++ = tmp_ctx.reg_values[1];
515
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600516 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600517 unsigned int i;
518 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700519 for (i = REG_A220_VSC_BIN_SIZE; i <=
520 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600521 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600522 *cmd++ = i;
523 *cmd++ = tmp_ctx.reg_values[j];
524 j++;
525 }
526 }
527
528 /* Copy Boolean constants */
529 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
530 BOOL_CONSTANTS);
531
532 /* Copy Loop constants */
533 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
534 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
535
536 /* create indirect buffer command for above command sequence */
537 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
538
539 tmp_ctx.cmd = cmd;
540}
541
542/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
543static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
544 struct adreno_context *drawctxt,
545 struct gmem_shadow_t *shadow)
546{
547 unsigned int *cmds = shadow->gmem_save_commands;
548 unsigned int *start = cmds;
549 /* Calculate the new offset based on the adjusted base */
550 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
551 unsigned int addr = shadow->gmemshadow.gpuaddr;
552 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
553
554 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600555 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600556 *cmds++ = REG_TP0_CHICKEN;
557
558 *cmds++ = tmp_ctx.chicken_restore;
559
Jordan Crouse084427d2011-07-28 08:37:58 -0600560 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600561 *cmds++ = 0;
562
563 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600564 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600565 *cmds++ = 0x00000000;
566
567 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600568 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600569 *cmds++ = 0x00000000;
570
571 /* program shader */
572
573 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600574 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600575 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
576 *cmds++ = 0;
577 /* valid(?) vtx constant flag & addr */
578 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
579 /* limit = 12 dwords */
580 *cmds++ = 0x00000030;
581
582 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600583 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600584 *cmds++ = 0x1;
585
Jordan Crouse084427d2011-07-28 08:37:58 -0600586 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600587 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600588 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
589 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
590 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
591
Jordan Crouse084427d2011-07-28 08:37:58 -0600592 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600593 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600594 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
595
Jordan Crouse084427d2011-07-28 08:37:58 -0600596 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600597 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600598 *cmds++ = 0x00000c20;
599
Tarun Karra16346b02011-07-24 15:04:26 -0700600 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600601 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700602 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700603
604 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600605 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700606 *cmds++ = 0x00003F00;
607
Jordan Crouse084427d2011-07-28 08:37:58 -0600608 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700609 *cmds++ = adreno_encode_istore_size(adreno_dev)
610 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700611
Jordan Crousea78c9172011-07-11 13:14:09 -0600612 /* load the patched vertex shader stream */
613 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
614
615 /* Load the patched fragment shader stream */
616 cmds =
617 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
618
619 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600620 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600621 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600622 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600623 *cmds++ = 0x10018001;
624 else
625 *cmds++ = 0x10010001;
626 *cmds++ = 0x00000008;
627
628 /* resolve */
629
630 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600631 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600632 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600633 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
634 *cmds++ = 0x00000b00;
635
636 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600637 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600638 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600639 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
640
641 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
642 * Base=gmem_base
643 */
644 /* gmem base assumed 4K aligned. */
645 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
646 *cmds++ =
647 (shadow->
648 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
649
650 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600651 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600652 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600653 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600654 *cmds++ = 0x08;
655 else
656 *cmds++ = 0;
657
658 /* set REG_PA_SU_SC_MODE_CNTL
659 * Front_ptype = draw triangles
660 * Back_ptype = draw triangles
661 * Provoking vertex = last
662 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600663 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600664 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600665 *cmds++ = 0x00080240;
666
667 /* Use maximum scissor values -- quad vertices already have the
668 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600669 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600670 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600671 *cmds++ = (0 << 16) | 0;
672 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600673 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600674 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600675 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
676 *cmds++ = (0x1fff << 16) | (0x1fff);
677
678 /* load the viewport so that z scale = clear depth and
679 * z offset = 0.0f
680 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600681 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600682 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600683 *cmds++ = 0xbf800000; /* -1.0f */
684 *cmds++ = 0x0;
685
Jordan Crouse084427d2011-07-28 08:37:58 -0600686 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600687 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600688 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
689
Jordan Crouse084427d2011-07-28 08:37:58 -0600690 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600691 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600692 *cmds++ = 0xffffffff;
693
Jordan Crouse084427d2011-07-28 08:37:58 -0600694 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600695 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600696 *cmds++ = 0x00000000;
697 *cmds++ = 0x00000000;
698
699 /* load the stencil ref value
700 * $AAM - do this later
701 */
702
703 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600704 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600705 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600706 *cmds++ = 0; /* RB_COPY_CONTROL */
707 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
708 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
709
710 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
711 * MaskWrite:R=G=B=A=1
712 */
713 *cmds++ = 0x0003c008 |
714 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
715 /* Make sure we stay in offsetx field. */
716 BUG_ON(offset & 0xfffff000);
717 *cmds++ = offset;
718
Jordan Crouse084427d2011-07-28 08:37:58 -0600719 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600720 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600721 *cmds++ = 0x6; /* EDRAM copy */
722
Jordan Crouse084427d2011-07-28 08:37:58 -0600723 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600724 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600725 *cmds++ = 0x00010000;
726
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600727 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600728 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600729 *cmds++ = 0;
730
Jordan Crouse084427d2011-07-28 08:37:58 -0600731 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700732 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600733 *cmds++ = 0x0000000;
734
Jordan Crouse084427d2011-07-28 08:37:58 -0600735 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600736 *cmds++ = 0; /* viz query info. */
737 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
738 *cmds++ = 0x00004088;
739 *cmds++ = 3; /* NumIndices=3 */
740 } else {
741 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600742 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600743 *cmds++ = 0; /* viz query info. */
744 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
745 *cmds++ = 0x00030088;
746 }
747
748 /* create indirect buffer command for above command sequence */
749 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
750
751 return cmds;
752}
753
754/* context restore */
755
756/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
757static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
758 struct adreno_context *drawctxt,
759 struct gmem_shadow_t *shadow)
760{
761 unsigned int *cmds = shadow->gmem_restore_commands;
762 unsigned int *start = cmds;
763
764 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600765 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600766 *cmds++ = REG_TP0_CHICKEN;
767 *cmds++ = tmp_ctx.chicken_restore;
768
Jordan Crouse084427d2011-07-28 08:37:58 -0600769 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600770 *cmds++ = 0;
771
772 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600773 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600774 *cmds++ = 0x00000000;
775
776 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600777 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600778 *cmds++ = 0x00000000;
779 /* shader constants */
780
781 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600782 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600783
784 *cmds++ = (0x1 << 16) | (9 * 6);
785 /* valid(?) vtx constant flag & addr */
786 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
787 /* limit = 12 dwords */
788 *cmds++ = 0x00000030;
789 /* valid(?) vtx constant flag & addr */
790 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
791 /* limit = 8 dwords */
792 *cmds++ = 0x00000020;
793 *cmds++ = 0;
794 *cmds++ = 0;
795
796 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600797 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600798 *cmds++ = 0x1;
799
800 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
801
Tarun Karra16346b02011-07-24 15:04:26 -0700802 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600803 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700804 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700805
806 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600807 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700808 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
809
Jordan Crouse084427d2011-07-28 08:37:58 -0600810 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700811 *cmds++ = adreno_encode_istore_size(adreno_dev)
812 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700813
Jordan Crousea78c9172011-07-11 13:14:09 -0600814 /* Load the patched fragment shader stream */
815 cmds =
816 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
817
818 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600819 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600820 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600821 *cmds++ = 0x10030002;
822 *cmds++ = 0x00000008;
823
Jordan Crouse084427d2011-07-28 08:37:58 -0600824 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600825 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600826 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
827
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600828 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600829 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600830 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600831 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600832 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
833 }
834
835 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600836 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600837 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600838 *cmds++ = 0x00000c20;
839
Jordan Crouse084427d2011-07-28 08:37:58 -0600840 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600841 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600842 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
843 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
844 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
845
Jordan Crouse084427d2011-07-28 08:37:58 -0600846 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600847 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600848 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
849 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
850
Jordan Crouse084427d2011-07-28 08:37:58 -0600851 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600852 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600853 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
854
Jordan Crouse084427d2011-07-28 08:37:58 -0600855 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600856 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600857 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
858
859 /* set REG_PA_SU_SC_MODE_CNTL
860 * Front_ptype = draw triangles
861 * Back_ptype = draw triangles
862 * Provoking vertex = last
863 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600864 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600865 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600866 *cmds++ = 0x00080240;
867
868 /* texture constants */
869 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600870 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600871 *cmds++ = (0x1 << 16) | (0 * 6);
872 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
873 cmds[0] |= (shadow->pitch >> 5) << 22;
874 cmds[1] |=
875 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
876 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
877 cmds += SYS2GMEM_TEX_CONST_LEN;
878
879 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600880 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600881 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600882 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
883
884 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
885 * Base=gmem_base
886 */
887 *cmds++ =
888 (shadow->
889 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
890
891 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600892 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600893 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600894
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600895 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600896 *cmds++ = 8; /* disable Z */
897 else
898 *cmds++ = 0; /* disable Z */
899
900 /* Use maximum scissor values -- quad vertices already
901 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600902 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600903 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600904 *cmds++ = (0 << 16) | 0;
905 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600906 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600907 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600908 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
909 *cmds++ = ((0x1fff) << 16) | 0x1fff;
910
Jordan Crouse084427d2011-07-28 08:37:58 -0600911 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600912 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600913 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
914 *cmds++ = 0x00000b00;
915
916 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600917 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600918 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600919 *cmds++ = 0xbf800000;
920 *cmds++ = 0x0;
921
Jordan Crouse084427d2011-07-28 08:37:58 -0600922 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600923 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600924 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
925
Jordan Crouse084427d2011-07-28 08:37:58 -0600926 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600927 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600928 *cmds++ = 0xffffffff;
929
Jordan Crouse084427d2011-07-28 08:37:58 -0600930 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600931 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600932 *cmds++ = 0x00000000;
933 *cmds++ = 0x00000000;
934
935 /* load the stencil ref value
936 * $AAM - do this later
937 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600938 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600939 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600940 /* draw pixels with color and depth/stencil component */
941 *cmds++ = 0x4;
942
Jordan Crouse084427d2011-07-28 08:37:58 -0600943 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600944 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600945 *cmds++ = 0x00010000;
946
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600947 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600948 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600949 *cmds++ = 0;
950
Jordan Crouse084427d2011-07-28 08:37:58 -0600951 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700952 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600953 *cmds++ = 0x0000000;
954
Jordan Crouse084427d2011-07-28 08:37:58 -0600955 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600956 *cmds++ = 0; /* viz query info. */
957 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
958 *cmds++ = 0x00004088;
959 *cmds++ = 3; /* NumIndices=3 */
960 } else {
961 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600962 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600963 *cmds++ = 0; /* viz query info. */
964 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
965 *cmds++ = 0x00030088;
966 }
967
968 /* create indirect buffer command for above command sequence */
969 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
970
971 return cmds;
972}
973
Jordan Crousea78c9172011-07-11 13:14:09 -0600974static void build_regrestore_cmds(struct adreno_device *adreno_dev,
975 struct adreno_context *drawctxt)
976{
977 unsigned int *start = tmp_ctx.cmd;
978 unsigned int *cmd = start;
979
980 unsigned int i = 0;
981 unsigned int reg_array_size = 0;
982 const unsigned int *ptr_register_ranges;
983
Jordan Crouse084427d2011-07-28 08:37:58 -0600984 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600985 *cmd++ = 0;
986
987 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -0600988 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -0600989 cmd++;
990#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
991 /* Force mismatch */
992 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
993#else
994 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
995#endif
996
997 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700998 if (adreno_is_a220(adreno_dev)) {
999 ptr_register_ranges = register_ranges_a220;
1000 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1001 } else if (adreno_is_a225(adreno_dev)) {
1002 ptr_register_ranges = register_ranges_a225;
1003 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001004 } else {
1005 ptr_register_ranges = register_ranges_a20x;
1006 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1007 }
1008
1009
1010 for (i = 0; i < (reg_array_size/2); i++) {
1011 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1012 ptr_register_ranges[i*2+1]);
1013 }
1014
1015 /* Now we know how many register blocks we have, we can compute command
1016 * length
1017 */
1018 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001019 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001020 /* Enable shadowing for the entire register block. */
1021#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1022 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1023#else
1024 start[4] |= (1 << 24) | (4 << 16);
1025#endif
1026
1027 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001028 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001029 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1030 *cmd++ = 0x00040400;
1031
Jordan Crouse084427d2011-07-28 08:37:58 -06001032 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001033 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001034 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001035 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1036 *cmd++ = 0x00000000;
1037
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001038 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001039 unsigned int i;
1040 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001041 for (i = REG_A220_VSC_BIN_SIZE; i <=
1042 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001043 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001044 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1045 &drawctxt->gpustate);
1046 *cmd++ = 0x00000000;
1047 j++;
1048 }
1049 }
1050
1051 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001052 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001053 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1054#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1055 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1056#else
1057 *cmd++ = (1 << 24) | (0 << 16) | 0;
1058#endif
1059 *cmd++ = ALU_CONSTANTS;
1060
1061 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001062 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001063 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1064#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1065 /* Disable shadowing */
1066 *cmd++ = (0 << 24) | (1 << 16) | 0;
1067#else
1068 *cmd++ = (1 << 24) | (1 << 16) | 0;
1069#endif
1070 *cmd++ = TEX_CONSTANTS;
1071
1072 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001073 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001074 *cmd++ = (2 << 16) | 0;
1075
1076 /* the next BOOL_CONSTANT dwords is the shadow area for
1077 * boolean constants.
1078 */
1079 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1080 cmd += BOOL_CONSTANTS;
1081
1082 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001083 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001084 *cmd++ = (3 << 16) | 0;
1085
1086 /* the next LOOP_CONSTANTS dwords is the shadow area for
1087 * loop constants.
1088 */
1089 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1090 cmd += LOOP_CONSTANTS;
1091
1092 /* create indirect buffer command for above command sequence */
1093 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1094
1095 tmp_ctx.cmd = cmd;
1096}
1097
Jordan Crousea78c9172011-07-11 13:14:09 -06001098static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001099build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1100 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001101{
1102 unsigned int *cmd = tmp_ctx.cmd;
1103 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001104 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001105 unsigned int *partition1;
1106 unsigned int *shaderBases, *partition2;
1107
Jordan Crousea78c9172011-07-11 13:14:09 -06001108 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1109 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001110 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1111 + _shader_shadow_size(adreno_dev);
1112 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1113 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001114
1115 /* restore shader partitioning and instructions */
1116
1117 restore = cmd; /* start address */
1118
1119 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001120 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001121 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1122
1123 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001124 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001125 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1126
1127 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001128 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001129 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1130
Jordan Crousea78c9172011-07-11 13:14:09 -06001131 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001132 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001133 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1134 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1135
1136 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001137 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001138 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1139 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1140
1141 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001142 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001143 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1144 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001145
1146 /* create indirect buffer command for above command sequence */
1147 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1148
1149 /*
1150 * fixup SET_SHADER_BASES data
1151 *
1152 * since self-modifying PM4 code is being used here, a seperate
1153 * command buffer is used for this fixup operation, to ensure the
1154 * commands are not read by the PM4 engine before the data fields
1155 * have been written.
1156 */
1157
1158 fixup = cmd; /* start address */
1159
1160 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001161 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001162 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1163
1164 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001165 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001166 *cmd++ = REG_SCRATCH_REG2;
1167 /* AND off invalid bits. */
1168 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001169 /* OR in instruction memory size. */
1170 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001171
1172 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001173 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001174 *cmd++ = REG_SCRATCH_REG2;
1175 /* TBD #5: shader bases (to restore) */
1176 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1177
1178 /* create indirect buffer command for above command sequence */
1179 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1180
1181 /* save shader partitioning and instructions */
1182
1183 save = cmd; /* start address */
1184
Jordan Crouse084427d2011-07-28 08:37:58 -06001185 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001186 *cmd++ = 0;
1187
1188 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1189 * store the value in the data fields of the SET_CONSTANT commands
1190 * above.
1191 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001192 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001193 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1194 /* TBD #4a: partition info (to restore) */
1195 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001196 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001197 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1198 /* TBD #4b: partition info (to fixup) */
1199 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1200
Jordan Crousea78c9172011-07-11 13:14:09 -06001201
1202 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001203 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001204 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1205 /* TBD #1: start/size (to restore) */
1206 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1207
1208 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001209 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001210 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1211 /* TBD #2: start/size (to restore) */
1212 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1213
1214 /* store the shared shader instructions if vertex base is nonzero */
1215
Jordan Crouse084427d2011-07-28 08:37:58 -06001216 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001217 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1218 /* TBD #3: start/size (to restore) */
1219 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1220
Jordan Crousea78c9172011-07-11 13:14:09 -06001221
Jordan Crouse084427d2011-07-28 08:37:58 -06001222 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001223 *cmd++ = 0;
1224
1225 /* create indirect buffer command for above command sequence */
1226 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1227
1228 tmp_ctx.cmd = cmd;
1229}
1230
1231/* create buffers for saving/restoring registers, constants, & GMEM */
1232static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1233 struct adreno_context *drawctxt)
1234{
1235 int result;
1236
1237 /* Allocate vmalloc memory to store the gpustate */
1238 result = kgsl_allocate(&drawctxt->gpustate,
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001239 drawctxt->pagetable, _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001240
1241 if (result)
1242 return result;
1243
1244 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1245
1246 /* Blank out h/w register, constant, and command buffer shadows. */
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001247 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1248 _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001249
1250 /* set-up command and vertex buffer pointers */
1251 tmp_ctx.cmd = tmp_ctx.start
1252 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1253
1254 /* build indirect command buffers to save & restore regs/constants */
1255 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1256 build_regrestore_cmds(adreno_dev, drawctxt);
1257 build_regsave_cmds(adreno_dev, drawctxt);
1258
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001259 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001260
1261 kgsl_cache_range_op(&drawctxt->gpustate,
1262 KGSL_CACHE_OP_FLUSH);
1263
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001264 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1265 drawctxt->gpustate.gpuaddr,
1266 drawctxt->gpustate.size, false);
Jordan Crousea78c9172011-07-11 13:14:09 -06001267 return 0;
1268}
1269
1270/* create buffers for saving/restoring registers, constants, & GMEM */
1271static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1272 struct adreno_context *drawctxt)
1273{
1274 int result;
1275
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001276 calc_gmemsize(&drawctxt->context_gmem_shadow,
1277 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001278 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1279
1280 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1281 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1282
1283 if (result)
1284 return result;
1285
1286 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1287 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1288
1289 /* blank out gmem shadow. */
1290 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1291 drawctxt->context_gmem_shadow.size);
1292
1293 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001294 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1295 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001296
1297 /* build TP0_CHICKEN register restore command buffer */
1298 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1299
1300 /* build indirect command buffers to save & restore gmem */
1301 /* Idle because we are reading PM override registers */
1302 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1303 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1304 tmp_ctx.cmd =
1305 build_gmem2sys_cmds(adreno_dev, drawctxt,
1306 &drawctxt->context_gmem_shadow);
1307 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1308 tmp_ctx.cmd =
1309 build_sys2gmem_cmds(adreno_dev, drawctxt,
1310 &drawctxt->context_gmem_shadow);
1311
1312 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1313 KGSL_CACHE_OP_FLUSH);
1314
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001315 kgsl_cffdump_syncmem(NULL,
1316 &drawctxt->context_gmem_shadow.gmemshadow,
1317 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1318 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1319
Jordan Crousea78c9172011-07-11 13:14:09 -06001320 return 0;
1321}
1322
1323static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1324 struct adreno_context *context)
1325{
1326 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001327 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001328
1329 if (context == NULL)
1330 return;
1331
1332 if (context->flags & CTXT_FLAGS_GPU_HANG)
1333 KGSL_CTXT_WARN(device,
1334 "Current active context has caused gpu hang\n");
1335
1336 KGSL_CTXT_INFO(device,
1337 "active context flags %08x\n", context->flags);
1338
1339 /* save registers and constants. */
1340 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1341
1342 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1343 /* save shader partitioning and instructions. */
1344 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1345 context->shader_save, 3);
1346
1347 /* fixup shader partitioning parameter for
1348 * SET_SHADER_BASES.
1349 */
1350 adreno_ringbuffer_issuecmds(device, 0,
1351 context->shader_fixup, 3);
1352
1353 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1354 }
1355
1356 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1357 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1358 /* save gmem.
1359 * (note: changes shader. shader must already be saved.)
1360 */
1361 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1362 context->context_gmem_shadow.gmem_save, 3);
1363
1364 /* Restore TP0_CHICKEN */
1365 adreno_ringbuffer_issuecmds(device, 0,
1366 context->chicken_restore, 3);
1367
1368 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001369 } else if (adreno_is_a225(adreno_dev)) {
1370 unsigned int *cmds = &cmd[0];
1371 /*
1372 * Issue an empty draw call to avoid possible hangs due to
1373 * repeated idles without intervening draw calls.
1374 * On adreno 225 the PC block has a cache that is only
1375 * flushed on draw calls and repeated idles can make it
1376 * overflow. The gmem save path contains draw calls so
1377 * this workaround isn't needed there.
1378 */
1379 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1380 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1381 *cmds++ = 0;
1382 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1383 *cmds++ = 0;
1384 *cmds++ = 1<<14;
1385 *cmds++ = 0;
1386 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1387 *cmds++ = 0;
1388 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1389 *cmds++ = 0x00000000;
1390
1391 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1392 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001393 }
1394}
1395
1396static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1397 struct adreno_context *context)
1398{
1399 struct kgsl_device *device = &adreno_dev->dev;
1400 unsigned int cmds[5];
1401
1402 if (context == NULL) {
1403 /* No context - set the default apgetable and thats it */
1404 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1405 return;
1406 }
1407
1408 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1409
Jordan Crouse084427d2011-07-28 08:37:58 -06001410 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001411 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001412 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001413 cmds[3] = device->memstore.gpuaddr +
1414 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1415 cmds[4] = (unsigned int) context;
1416 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1417 kgsl_mmu_setstate(device, context->pagetable);
1418
1419#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1420 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1421 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1422 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1423#endif
1424
1425 /* restore gmem.
1426 * (note: changes shader. shader must not already be restored.)
1427 */
1428 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1429 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1430 context->context_gmem_shadow.gmem_restore, 3);
1431
1432 /* Restore TP0_CHICKEN */
1433 adreno_ringbuffer_issuecmds(device, 0,
1434 context->chicken_restore, 3);
1435
1436 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1437 }
1438
1439 /* restore registers and constants. */
1440 adreno_ringbuffer_issuecmds(device, 0,
1441 context->reg_restore, 3);
1442
1443 /* restore shader instructions & partitioning. */
1444 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1445 adreno_ringbuffer_issuecmds(device, 0,
1446 context->shader_restore, 3);
1447 }
1448
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001449 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001450 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001451 cmds[1] = context->bin_base_offset;
Jordan Crousea78c9172011-07-11 13:14:09 -06001452 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001453 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001454}
1455
1456/*
1457 * Interrupt management
1458 *
1459 * a2xx interrupt control is distributed among the various
1460 * hardware components (RB, CP, MMU). The main interrupt
1461 * tells us which component fired the interrupt, but one needs
1462 * to go to the individual component to find out why. The
1463 * following functions provide the broken out support for
1464 * managing the interrupts
1465 */
1466
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001467#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001468
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001469#define CP_INT_MASK \
1470 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001471 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1472 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1473 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1474 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001475 CP_INT_CNTL__IB1_INT_MASK | \
1476 CP_INT_CNTL__RB_INT_MASK)
1477
1478#define VALID_STATUS_COUNT_MAX 10
1479
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001480static struct {
1481 unsigned int mask;
1482 const char *message;
1483} kgsl_cp_error_irqs[] = {
1484 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1485 "ringbuffer TO packet in IB interrupt" },
1486 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1487 "ringbuffer opcode error interrupt" },
1488 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1489 "ringbuffer protected mode error interrupt" },
1490 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1491 "ringbuffer reserved bit error interrupt" },
1492 { CP_INT_CNTL__IB_ERROR_MASK,
1493 "ringbuffer IB error interrupt" },
1494};
1495
Jordan Crousea78c9172011-07-11 13:14:09 -06001496static void a2xx_cp_intrcallback(struct kgsl_device *device)
1497{
1498 unsigned int status = 0, num_reads = 0, master_status = 0;
1499 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1500 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001501 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001502
1503 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1504 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1505 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1506 adreno_regread(device, REG_CP_INT_STATUS, &status);
1507 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1508 &master_status);
1509 num_reads++;
1510 }
1511 if (num_reads > 1)
1512 KGSL_DRV_WARN(device,
1513 "Looped %d times to read REG_CP_INT_STATUS\n",
1514 num_reads);
Norman Geed7402ff2011-10-28 08:51:11 -06001515
1516 trace_kgsl_a2xx_irq_status(device, master_status, status);
1517
Jordan Crousea78c9172011-07-11 13:14:09 -06001518 if (!status) {
1519 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1520 /* This indicates that we could not read CP_INT_STAT.
1521 * As a precaution just wake up processes so
1522 * they can check their timestamps. Since, we
1523 * did not ack any interrupts this interrupt will
1524 * be generated again */
1525 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1526 wake_up_interruptible_all(&device->wait_queue);
1527 } else
1528 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1529 return;
1530 }
1531
1532 if (status & CP_INT_CNTL__RB_INT_MASK) {
1533 /* signal intr completion event */
1534 unsigned int enableflag = 0;
1535 kgsl_sharedmem_writel(&rb->device->memstore,
1536 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1537 enableflag);
1538 wmb();
1539 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1540 }
1541
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001542 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1543 if (status & kgsl_cp_error_irqs[i].mask) {
1544 KGSL_CMD_CRIT(rb->device, "%s\n",
1545 kgsl_cp_error_irqs[i].message);
1546 /*
1547 * on fatal errors, turn off the interrupts to
1548 * avoid storming. This has the side effect of
1549 * forcing a PM dump when the timestamp times out
1550 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001551
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001552 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1553 }
1554 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001555
1556 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001557 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001558 adreno_regwrite(device, REG_CP_INT_ACK, status);
1559
1560 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1561 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001562 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001563 wake_up_interruptible_all(&device->wait_queue);
1564 atomic_notifier_call_chain(&(device->ts_notifier_list),
1565 device->id,
1566 NULL);
1567 }
1568}
1569
1570static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1571{
1572 unsigned int status = 0;
1573 unsigned int rderr = 0;
1574
1575 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1576
1577 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1578 union rbbm_read_error_u rerr;
1579 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1580 rerr.val = rderr;
1581 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1582 rerr.f.read_error &&
1583 rerr.f.read_requester)
1584 KGSL_DRV_WARN(device,
1585 "rbbm read error interrupt: %08x\n", rderr);
1586 else
1587 KGSL_DRV_CRIT(device,
1588 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001589 }
1590
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001591 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001592 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1593}
1594
1595irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1596{
1597 struct kgsl_device *device = &adreno_dev->dev;
1598 irqreturn_t result = IRQ_NONE;
1599 unsigned int status;
1600
1601 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1602
1603 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1604 kgsl_mh_intrcallback(device);
1605 result = IRQ_HANDLED;
1606 }
1607
1608 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1609 a2xx_cp_intrcallback(device);
1610 result = IRQ_HANDLED;
1611 }
1612
1613 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1614 a2xx_rbbm_intrcallback(device);
1615 result = IRQ_HANDLED;
1616 }
1617
1618 return result;
1619}
1620
1621static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1622{
1623 struct kgsl_device *device = &adreno_dev->dev;
1624
1625 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001626 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1627 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001628 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1629 } else {
1630 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1631 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1632 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1633 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001634
1635 /* Force the writes to post before touching the IRQ line */
1636 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001637}
1638
1639struct adreno_gpudev adreno_a2xx_gpudev = {
1640 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1641 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1642 .ctxt_save = a2xx_ctxt_save,
1643 .ctxt_restore = a2xx_ctxt_restore,
1644 .irq_handler = a2xx_irq_handler,
1645 .irq_control = a2xx_irq_control,
1646};