blob: cf9a60aa07e1541fd6f3c5ecedf0d628c9a29ac1 [file] [log] [blame]
Jordan Crousef7597bf2012-01-03 08:43:34 -07001/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
Jordan Crousea78c9172011-07-11 13:14:09 -06002 *
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/*
Jordan Crousef7597bf2012-01-03 08:43:34 -070021 * These are the registers that are dumped with GPU snapshot
22 * and postmortem. The lists are dword offset pairs in the
23 * form of {start offset, end offset} inclusive.
24 */
25
26/* A200, A205 */
27const unsigned int a200_registers[] = {
28 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
29 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
30 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
31 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
32 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
33 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
34 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
35 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
36 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
37 0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
38 0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
39 0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
40 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
41 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
42 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
43 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
44 0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
45 0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
46 0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
47 0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
48 0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
49 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
50 0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
51 0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
52 0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
53};
54
55/* A220, A225 */
56const unsigned int a220_registers[] = {
57 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
58 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
59 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
60 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
61 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
62 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
63 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
64 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
65 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
66 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
67 0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
68 0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
69 0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
70 0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
71 0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
72 0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
73 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
74 0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
75 0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
76 0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
77 0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
78 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
79 0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
80 0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
81 0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
82 0x4900, 0x4900, 0x4908, 0x4908,
83};
84
85const unsigned int a200_registers_count = ARRAY_SIZE(a200_registers) / 2;
86const unsigned int a220_registers_count = ARRAY_SIZE(a220_registers) / 2;
87
88/*
Jordan Crousea78c9172011-07-11 13:14:09 -060089 *
90 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
91 * (34.5KB)
92 *
93 * +---------------------+------------+-------------+---+---------------------+
94 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
95 * +---------------------+------------+-------------+---+---------------------+
96 * ________________________________/ \____________________
97 * / |
98 * +--------------+-----------+------+-----------+------------------------+
99 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
100 * +--------------+-----------+------+-----------+------------------------+
101 *
102 * 8K - ALU Constant Shadow (8K aligned)
103 * 4K - H/W Register Shadow (8K aligned)
104 * 4K - Command and Vertex Buffers
105 * - Indirect command buffer : Const/Reg restore
106 * - includes Loop & Bool const shadows
107 * - Indirect command buffer : Const/Reg save
108 * - Quad vertices & texture coordinates
109 * - Indirect command buffer : Gmem save
110 * - Indirect command buffer : Gmem restore
111 * - Unused (padding to 8KB boundary)
112 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
113 * 18K - Shader Instruction Shadow
114 * - 6K vertex (32 byte aligned)
115 * - 6K pixel (32 byte aligned)
116 * - 6K shared (32 byte aligned)
117 *
118 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
119 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
120 * 16 bytes per constant. If the texture constants were transfered this way,
121 * the Command & Vertex Buffers section would extend past the 16K boundary.
122 * By moving the texture constant shadow area to start at 16KB boundary, we
123 * only require approximately 40 bytes more memory, but are able to use the
124 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
125 * context switching.
126 *
127 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
128 * constants would require an additional 8KB each, for alignment.]
129 *
130 */
131
132/* Constants */
133
134#define ALU_CONSTANTS 2048 /* DWORDS */
135#define NUM_REGISTERS 1024 /* DWORDS */
136#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
137#define CMD_BUFFER_LEN 9216 /* DWORDS */
138#else
139#define CMD_BUFFER_LEN 3072 /* DWORDS */
140#endif
141#define TEX_CONSTANTS (32*6) /* DWORDS */
142#define BOOL_CONSTANTS 8 /* DWORDS */
143#define LOOP_CONSTANTS 56 /* DWORDS */
Jordan Crousea78c9172011-07-11 13:14:09 -0600144
145/* LOAD_CONSTANT_CONTEXT shadow size */
146#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
147
148#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
149#define REG_SHADOW_SIZE 0x1000 /* 4KB */
150#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
151#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
152#else
153#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
154#endif
155#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
Jordan Crousea78c9172011-07-11 13:14:09 -0600156
157#define REG_OFFSET LCC_SHADOW_SIZE
158#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
159#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
160#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
161
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700162static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
163{
164 return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
165}
166
167static inline int _context_size(struct adreno_device *adreno_dev)
168{
169 return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
170}
Jordan Crousea78c9172011-07-11 13:14:09 -0600171
172/* A scratchpad used to build commands during context create */
173
174static struct tmp_ctx {
175 unsigned int *start; /* Command & Vertex buffer start */
176 unsigned int *cmd; /* Next available dword in C&V buffer */
177
178 /* address of buffers, needed when creating IB1 command buffers. */
179 uint32_t bool_shadow; /* bool constants */
180 uint32_t loop_shadow; /* loop constants */
181
Jordan Crousea78c9172011-07-11 13:14:09 -0600182 uint32_t shader_shared; /* shared shader instruction shadow */
183 uint32_t shader_vertex; /* vertex shader instruction shadow */
184 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600185
186 /* Addresses in command buffer where separately handled registers
187 * are saved
188 */
189 uint32_t reg_values[33];
190 uint32_t chicken_restore;
191
192 uint32_t gmem_base; /* Base gpu address of GMEM */
193
194} tmp_ctx;
195
196/* context save (gmem -> sys) */
197
198/* pre-compiled vertex shader program
199*
200* attribute vec4 P;
201* void main(void)
202* {
203* gl_Position = P;
204* }
205*/
206#define GMEM2SYS_VTX_PGM_LEN 0x12
207
208static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
209 0x00011003, 0x00001000, 0xc2000000,
210 0x00001004, 0x00001000, 0xc4000000,
211 0x00001005, 0x00002000, 0x00000000,
212 0x1cb81000, 0x00398a88, 0x00000003,
213 0x140f803e, 0x00000000, 0xe2010100,
214 0x14000000, 0x00000000, 0xe2000000
215};
216
217/* pre-compiled fragment shader program
218*
219* precision highp float;
220* uniform vec4 clear_color;
221* void main(void)
222* {
223* gl_FragColor = clear_color;
224* }
225*/
226
227#define GMEM2SYS_FRAG_PGM_LEN 0x0c
228
229static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
230 0x00000000, 0x1002c400, 0x10000000,
231 0x00001003, 0x00002000, 0x00000000,
232 0x140f8000, 0x00000000, 0x22000000,
233 0x14000000, 0x00000000, 0xe2000000
234};
235
236/* context restore (sys -> gmem) */
237/* pre-compiled vertex shader program
238*
239* attribute vec4 position;
240* attribute vec4 texcoord;
241* varying vec4 texcoord0;
242* void main()
243* {
244* gl_Position = position;
245* texcoord0 = texcoord;
246* }
247*/
248
249#define SYS2GMEM_VTX_PGM_LEN 0x18
250
251static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
252 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
253 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
254 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
255 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
256 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
257 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
258};
259
260/* pre-compiled fragment shader program
261*
262* precision mediump float;
263* uniform sampler2D tex0;
264* varying vec4 texcoord0;
265* void main()
266* {
267* gl_FragColor = texture2D(tex0, texcoord0.xy);
268* }
269*/
270
271#define SYS2GMEM_FRAG_PGM_LEN 0x0f
272
273static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
274 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
275 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
276 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
277 0x14000000, 0x00000000, 0xe2000000
278};
279
280/* shader texture constants (sysmem -> gmem) */
281#define SYS2GMEM_TEX_CONST_LEN 6
282
283static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
284 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
285 * RFMode=ZeroClamp-1, Dim=1:2d
286 */
287 0x00000002, /* Pitch = TBD */
288
289 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
290 * NearestClamp=1:OGL Mode
291 */
292 0x00000800, /* Address[31:12] = TBD */
293
294 /* Width, Height, EndianSwap=0:None */
295 0, /* Width & Height = TBD */
296
297 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
298 * Mip=2:BaseMap
299 */
300 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
301
302 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
303 * Dim3d=0
304 */
305 0,
306
307 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
308 * Dim=1:2d, MipPacking=0
309 */
310 1 << 9 /* Mip Address[31:12] = TBD */
311};
312
Jordan Crousea78c9172011-07-11 13:14:09 -0600313#define NUM_COLOR_FORMATS 13
314
315static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
316 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
317 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
318 FMT_5_6_5, /* COLORX_5_6_5 */
319 FMT_8, /* COLORX_8 */
320 FMT_8_8, /* COLORX_8_8 */
321 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
322 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
323 FMT_16_FLOAT, /* COLORX_16_FLOAT */
324 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
325 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
326 FMT_32_FLOAT, /* COLORX_32_FLOAT */
327 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
328 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
329};
330
331static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
332 2, /* COLORX_4_4_4_4 */
333 2, /* COLORX_1_5_5_5 */
334 2, /* COLORX_5_6_5 */
335 1, /* COLORX_8 */
336 2, /* COLORX_8_8 8*/
337 4, /* COLORX_8_8_8_8 */
338 4, /* COLORX_S8_8_8_8 */
339 2, /* COLORX_16_FLOAT */
340 4, /* COLORX_16_16_FLOAT */
341 8, /* COLORX_16_16_16_16_FLOAT */
342 4, /* COLORX_32_FLOAT */
343 8, /* COLORX_32_32_FLOAT */
344 16, /* COLORX_32_32_32_32_FLOAT */
345};
346
347/* shader linkage info */
348#define SHADER_CONST_ADDR (11 * 6 + 3)
349
Jordan Crousea78c9172011-07-11 13:14:09 -0600350
351static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
352 unsigned int *shader_pgm, int dwords)
353{
354 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600355 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600356 /* 0=vertex shader, 1=fragment shader */
357 *cmds++ = vtxfrag;
358 /* instruction start & size (in 32-bit words) */
359 *cmds++ = ((0 << 16) | dwords);
360
361 memcpy(cmds, shader_pgm, dwords << 2);
362 cmds += dwords;
363
364 return cmds;
365}
366
367static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
368 uint32_t src, int dwords)
369{
370 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600371 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600372 *cmds++ = src++;
373 *cmds++ = dst;
374 dst += 4;
375 }
376
377 return cmds;
378}
379
380#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
381
382static void build_reg_to_mem_range(unsigned int start, unsigned int end,
383 unsigned int **cmd,
384 struct adreno_context *drawctxt)
385{
386 unsigned int i = start;
387
388 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600389 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600390 *(*cmd)++ = i;
391 *(*cmd)++ =
392 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
393 (i - 0x2000) * 4;
394 }
395}
396
397#endif
398
399/* chicken restore */
400static unsigned int *build_chicken_restore_cmds(
401 struct adreno_context *drawctxt)
402{
403 unsigned int *start = tmp_ctx.cmd;
404 unsigned int *cmds = start;
405
Jordan Crouse084427d2011-07-28 08:37:58 -0600406 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600407 *cmds++ = 0;
408
Jordan Crouse084427d2011-07-28 08:37:58 -0600409 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600410 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
411 *cmds++ = 0x00000000;
412
413 /* create indirect buffer command for above command sequence */
414 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
415
416 return cmds;
417}
418
419/****************************************************************************/
420/* context save */
421/****************************************************************************/
422
423static const unsigned int register_ranges_a20x[] = {
424 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
425 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
426 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
427 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
428 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
429 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
430 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
431 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
432 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
433 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
434 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
435 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
436 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
437 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
438};
439
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700440static const unsigned int register_ranges_a220[] = {
Jordan Crousea78c9172011-07-11 13:14:09 -0600441 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
442 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
443 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
444 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
445 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
446 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
447 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
448 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
449 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700450 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600451 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
452 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
453 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
454 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
455 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700456 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
457 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600458 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
459};
460
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700461static const unsigned int register_ranges_a225[] = {
462 REG_RB_SURFACE_INFO, REG_A225_RB_COLOR_INFO3,
463 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
464 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
465 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
466 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
467 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
468 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
469 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
470 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
471 REG_A220_PC_MAX_VTX_INDX, REG_A225_PC_MULTI_PRIM_IB_RESET_INDX,
472 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
473 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
474 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
475 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
476 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
477 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
478 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
479 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
Jeremy Gebbene139a042011-11-17 16:20:41 -0700480 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
481 REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700482};
483
Jordan Crousea78c9172011-07-11 13:14:09 -0600484
485/* save h/w regs, alu constants, texture contants, etc. ...
486* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
487*/
488static void build_regsave_cmds(struct adreno_device *adreno_dev,
489 struct adreno_context *drawctxt)
490{
491 unsigned int *start = tmp_ctx.cmd;
492 unsigned int *cmd = start;
493
Jordan Crouse084427d2011-07-28 08:37:58 -0600494 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600495 *cmd++ = 0;
496
497#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
498 /* Make sure the HW context has the correct register values
499 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600500 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600501 *cmd++ = 0;
502
503 {
504 unsigned int i = 0;
505 unsigned int reg_array_size = 0;
506 const unsigned int *ptr_register_ranges;
507
508 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700509 if (adreno_is_a220(adreno_dev)) {
510 ptr_register_ranges = register_ranges_a220;
511 reg_array_size = ARRAY_SIZE(register_ranges_a220);
512 } else if (adreno_is_a225(adreno_dev)) {
513 ptr_register_ranges = register_ranges_a225;
514 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600515 } else {
516 ptr_register_ranges = register_ranges_a20x;
517 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
518 }
519
520
521 /* Write HW registers into shadow */
522 for (i = 0; i < (reg_array_size/2) ; i++) {
523 build_reg_to_mem_range(ptr_register_ranges[i*2],
524 ptr_register_ranges[i*2+1],
525 &cmd, drawctxt);
526 }
527 }
528
529 /* Copy ALU constants */
530 cmd =
531 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
532 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
533
534 /* Copy Tex constants */
535 cmd =
536 reg_to_mem(cmd,
537 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
538 REG_SQ_FETCH_0, TEX_CONSTANTS);
539#else
540
541 /* Insert a wait for idle packet before reading the registers.
542 * This is to fix a hang/reset seen during stress testing. In this
543 * hang, CP encountered a timeout reading SQ's boolean constant
544 * register. There is logic in the HW that blocks reading of this
545 * register when the SQ block is not idle, which we believe is
546 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600547 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600548 *cmd++ = 0;
549
550 /* H/w registers are already shadowed; just need to disable shadowing
551 * to prevent corruption.
552 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600553 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600554 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
555 *cmd++ = 4 << 16; /* regs, start=0 */
556 *cmd++ = 0x0; /* count = 0 */
557
558 /* ALU constants are already shadowed; just need to disable shadowing
559 * to prevent corruption.
560 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600561 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600562 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
563 *cmd++ = 0 << 16; /* ALU, start=0 */
564 *cmd++ = 0x0; /* count = 0 */
565
566 /* Tex constants are already shadowed; just need to disable shadowing
567 * to prevent corruption.
568 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600569 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600570 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
571 *cmd++ = 1 << 16; /* Tex, start=0 */
572 *cmd++ = 0x0; /* count = 0 */
573#endif
574
575 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600576 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600577 *cmd++ = REG_SQ_GPR_MANAGEMENT;
578 *cmd++ = tmp_ctx.reg_values[0];
579
Jordan Crouse084427d2011-07-28 08:37:58 -0600580 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600581 *cmd++ = REG_TP0_CHICKEN;
582 *cmd++ = tmp_ctx.reg_values[1];
583
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600584 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600585 unsigned int i;
586 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700587 for (i = REG_A220_VSC_BIN_SIZE; i <=
588 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600589 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600590 *cmd++ = i;
591 *cmd++ = tmp_ctx.reg_values[j];
592 j++;
593 }
594 }
595
596 /* Copy Boolean constants */
597 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
598 BOOL_CONSTANTS);
599
600 /* Copy Loop constants */
601 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
602 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
603
604 /* create indirect buffer command for above command sequence */
605 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
606
607 tmp_ctx.cmd = cmd;
608}
609
610/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
611static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
612 struct adreno_context *drawctxt,
613 struct gmem_shadow_t *shadow)
614{
615 unsigned int *cmds = shadow->gmem_save_commands;
616 unsigned int *start = cmds;
617 /* Calculate the new offset based on the adjusted base */
618 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
619 unsigned int addr = shadow->gmemshadow.gpuaddr;
620 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
621
622 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600623 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600624 *cmds++ = REG_TP0_CHICKEN;
625
626 *cmds++ = tmp_ctx.chicken_restore;
627
Jordan Crouse084427d2011-07-28 08:37:58 -0600628 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600629 *cmds++ = 0;
630
631 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600632 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600633 *cmds++ = 0x00000000;
634
635 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600636 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600637 *cmds++ = 0x00000000;
638
639 /* program shader */
640
641 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600642 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600643 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
644 *cmds++ = 0;
645 /* valid(?) vtx constant flag & addr */
646 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
647 /* limit = 12 dwords */
648 *cmds++ = 0x00000030;
649
650 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600651 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600652 *cmds++ = 0x1;
653
Jordan Crouse084427d2011-07-28 08:37:58 -0600654 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600655 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600656 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
657 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
658 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
659
Jordan Crouse084427d2011-07-28 08:37:58 -0600660 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600661 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600662 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
663
Jordan Crouse084427d2011-07-28 08:37:58 -0600664 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600665 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600666 *cmds++ = 0x00000c20;
667
Tarun Karra16346b02011-07-24 15:04:26 -0700668 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600669 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700670 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700671
672 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600673 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700674 *cmds++ = 0x00003F00;
675
Jordan Crouse084427d2011-07-28 08:37:58 -0600676 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700677 *cmds++ = adreno_encode_istore_size(adreno_dev)
678 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700679
Jordan Crousea78c9172011-07-11 13:14:09 -0600680 /* load the patched vertex shader stream */
681 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
682
683 /* Load the patched fragment shader stream */
684 cmds =
685 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
686
687 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600688 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600689 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600690 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600691 *cmds++ = 0x10018001;
692 else
693 *cmds++ = 0x10010001;
694 *cmds++ = 0x00000008;
695
696 /* resolve */
697
698 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600699 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600700 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600701 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
702 *cmds++ = 0x00000b00;
703
704 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600705 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600706 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600707 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
708
709 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
710 * Base=gmem_base
711 */
712 /* gmem base assumed 4K aligned. */
713 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
714 *cmds++ =
715 (shadow->
716 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
717
718 /* disable Z */
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_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600721 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600722 *cmds++ = 0x08;
723 else
724 *cmds++ = 0;
725
726 /* set REG_PA_SU_SC_MODE_CNTL
727 * Front_ptype = draw triangles
728 * Back_ptype = draw triangles
729 * Provoking vertex = last
730 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600731 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600732 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600733 *cmds++ = 0x00080240;
734
735 /* Use maximum scissor values -- quad vertices already have the
736 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600737 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600738 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600739 *cmds++ = (0 << 16) | 0;
740 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600741 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600742 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600743 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
744 *cmds++ = (0x1fff << 16) | (0x1fff);
745
746 /* load the viewport so that z scale = clear depth and
747 * z offset = 0.0f
748 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600749 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600750 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600751 *cmds++ = 0xbf800000; /* -1.0f */
752 *cmds++ = 0x0;
753
Jordan Crouse084427d2011-07-28 08:37:58 -0600754 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600755 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600756 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
757
Jordan Crouse084427d2011-07-28 08:37:58 -0600758 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600759 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600760 *cmds++ = 0xffffffff;
761
Jordan Crouse084427d2011-07-28 08:37:58 -0600762 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600763 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600764 *cmds++ = 0x00000000;
765 *cmds++ = 0x00000000;
766
767 /* load the stencil ref value
768 * $AAM - do this later
769 */
770
771 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600772 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600773 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600774 *cmds++ = 0; /* RB_COPY_CONTROL */
775 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
776 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
777
778 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
779 * MaskWrite:R=G=B=A=1
780 */
781 *cmds++ = 0x0003c008 |
782 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
783 /* Make sure we stay in offsetx field. */
784 BUG_ON(offset & 0xfffff000);
785 *cmds++ = offset;
786
Jordan Crouse084427d2011-07-28 08:37:58 -0600787 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600788 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600789 *cmds++ = 0x6; /* EDRAM copy */
790
Jordan Crouse084427d2011-07-28 08:37:58 -0600791 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600792 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600793 *cmds++ = 0x00010000;
794
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600795 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600796 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600797 *cmds++ = 0;
798
Jordan Crouse084427d2011-07-28 08:37:58 -0600799 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700800 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600801 *cmds++ = 0x0000000;
802
Jordan Crouse084427d2011-07-28 08:37:58 -0600803 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600804 *cmds++ = 0; /* viz query info. */
805 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
806 *cmds++ = 0x00004088;
807 *cmds++ = 3; /* NumIndices=3 */
808 } else {
809 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600810 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600811 *cmds++ = 0; /* viz query info. */
812 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
813 *cmds++ = 0x00030088;
814 }
815
816 /* create indirect buffer command for above command sequence */
817 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
818
819 return cmds;
820}
821
822/* context restore */
823
824/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
825static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
826 struct adreno_context *drawctxt,
827 struct gmem_shadow_t *shadow)
828{
829 unsigned int *cmds = shadow->gmem_restore_commands;
830 unsigned int *start = cmds;
831
832 /* Store TP0_CHICKEN register */
Jordan Crouse084427d2011-07-28 08:37:58 -0600833 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600834 *cmds++ = REG_TP0_CHICKEN;
835 *cmds++ = tmp_ctx.chicken_restore;
836
Jordan Crouse084427d2011-07-28 08:37:58 -0600837 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600838 *cmds++ = 0;
839
840 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600841 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600842 *cmds++ = 0x00000000;
843
844 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600845 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600846 *cmds++ = 0x00000000;
847 /* shader constants */
848
849 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600850 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600851
852 *cmds++ = (0x1 << 16) | (9 * 6);
853 /* valid(?) vtx constant flag & addr */
854 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
855 /* limit = 12 dwords */
856 *cmds++ = 0x00000030;
857 /* valid(?) vtx constant flag & addr */
858 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
859 /* limit = 8 dwords */
860 *cmds++ = 0x00000020;
861 *cmds++ = 0;
862 *cmds++ = 0;
863
864 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600865 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600866 *cmds++ = 0x1;
867
868 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
869
Tarun Karra16346b02011-07-24 15:04:26 -0700870 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600871 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700872 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700873
874 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600875 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700876 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
877
Jordan Crouse084427d2011-07-28 08:37:58 -0600878 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700879 *cmds++ = adreno_encode_istore_size(adreno_dev)
880 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700881
Jordan Crousea78c9172011-07-11 13:14:09 -0600882 /* Load the patched fragment shader stream */
883 cmds =
884 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
885
886 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600887 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600888 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600889 *cmds++ = 0x10030002;
890 *cmds++ = 0x00000008;
891
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_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600894 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
895
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600896 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600897 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600898 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600899 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600900 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
901 }
902
903 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600904 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600905 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600906 *cmds++ = 0x00000c20;
907
Jordan Crouse084427d2011-07-28 08:37:58 -0600908 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600909 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600910 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
911 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
912 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
913
Jordan Crouse084427d2011-07-28 08:37:58 -0600914 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600915 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600916 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
917 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
918
Jordan Crouse084427d2011-07-28 08:37:58 -0600919 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600920 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600921 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
922
Jordan Crouse084427d2011-07-28 08:37:58 -0600923 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600924 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600925 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
926
927 /* set REG_PA_SU_SC_MODE_CNTL
928 * Front_ptype = draw triangles
929 * Back_ptype = draw triangles
930 * Provoking vertex = last
931 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600932 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600933 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600934 *cmds++ = 0x00080240;
935
936 /* texture constants */
937 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600938 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600939 *cmds++ = (0x1 << 16) | (0 * 6);
940 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
941 cmds[0] |= (shadow->pitch >> 5) << 22;
942 cmds[1] |=
943 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
944 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
945 cmds += SYS2GMEM_TEX_CONST_LEN;
946
947 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600948 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600949 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600950 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
951
952 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
953 * Base=gmem_base
954 */
955 *cmds++ =
956 (shadow->
957 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
958
959 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600960 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600961 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600962
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600963 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600964 *cmds++ = 8; /* disable Z */
965 else
966 *cmds++ = 0; /* disable Z */
967
968 /* Use maximum scissor values -- quad vertices already
969 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600970 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600971 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600972 *cmds++ = (0 << 16) | 0;
973 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600974 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600975 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600976 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
977 *cmds++ = ((0x1fff) << 16) | 0x1fff;
978
Jordan Crouse084427d2011-07-28 08:37:58 -0600979 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600980 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600981 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
982 *cmds++ = 0x00000b00;
983
984 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600985 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600986 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600987 *cmds++ = 0xbf800000;
988 *cmds++ = 0x0;
989
Jordan Crouse084427d2011-07-28 08:37:58 -0600990 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600991 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600992 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
993
Jordan Crouse084427d2011-07-28 08:37:58 -0600994 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600995 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600996 *cmds++ = 0xffffffff;
997
Jordan Crouse084427d2011-07-28 08:37:58 -0600998 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600999 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -06001000 *cmds++ = 0x00000000;
1001 *cmds++ = 0x00000000;
1002
1003 /* load the stencil ref value
1004 * $AAM - do this later
1005 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001006 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001007 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001008 /* draw pixels with color and depth/stencil component */
1009 *cmds++ = 0x4;
1010
Jordan Crouse084427d2011-07-28 08:37:58 -06001011 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001012 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001013 *cmds++ = 0x00010000;
1014
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001015 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001016 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001017 *cmds++ = 0;
1018
Jordan Crouse084427d2011-07-28 08:37:58 -06001019 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001020 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001021 *cmds++ = 0x0000000;
1022
Jordan Crouse084427d2011-07-28 08:37:58 -06001023 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001024 *cmds++ = 0; /* viz query info. */
1025 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
1026 *cmds++ = 0x00004088;
1027 *cmds++ = 3; /* NumIndices=3 */
1028 } else {
1029 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -06001030 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001031 *cmds++ = 0; /* viz query info. */
1032 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
1033 *cmds++ = 0x00030088;
1034 }
1035
1036 /* create indirect buffer command for above command sequence */
1037 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
1038
1039 return cmds;
1040}
1041
Jordan Crousea78c9172011-07-11 13:14:09 -06001042static void build_regrestore_cmds(struct adreno_device *adreno_dev,
1043 struct adreno_context *drawctxt)
1044{
1045 unsigned int *start = tmp_ctx.cmd;
1046 unsigned int *cmd = start;
1047
1048 unsigned int i = 0;
1049 unsigned int reg_array_size = 0;
1050 const unsigned int *ptr_register_ranges;
1051
Jordan Crouse084427d2011-07-28 08:37:58 -06001052 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001053 *cmd++ = 0;
1054
1055 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -06001056 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -06001057 cmd++;
1058#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1059 /* Force mismatch */
1060 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1061#else
1062 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1063#endif
1064
1065 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -07001066 if (adreno_is_a220(adreno_dev)) {
1067 ptr_register_ranges = register_ranges_a220;
1068 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1069 } else if (adreno_is_a225(adreno_dev)) {
1070 ptr_register_ranges = register_ranges_a225;
1071 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001072 } else {
1073 ptr_register_ranges = register_ranges_a20x;
1074 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1075 }
1076
1077
1078 for (i = 0; i < (reg_array_size/2); i++) {
1079 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1080 ptr_register_ranges[i*2+1]);
1081 }
1082
1083 /* Now we know how many register blocks we have, we can compute command
1084 * length
1085 */
1086 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001087 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001088 /* Enable shadowing for the entire register block. */
1089#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1090 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1091#else
1092 start[4] |= (1 << 24) | (4 << 16);
1093#endif
1094
1095 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001096 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001097 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1098 *cmd++ = 0x00040400;
1099
Jordan Crouse084427d2011-07-28 08:37:58 -06001100 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001101 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001102 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001103 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1104 *cmd++ = 0x00000000;
1105
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001106 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001107 unsigned int i;
1108 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001109 for (i = REG_A220_VSC_BIN_SIZE; i <=
1110 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001111 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001112 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1113 &drawctxt->gpustate);
1114 *cmd++ = 0x00000000;
1115 j++;
1116 }
1117 }
1118
1119 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001120 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001121 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1122#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1123 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1124#else
1125 *cmd++ = (1 << 24) | (0 << 16) | 0;
1126#endif
1127 *cmd++ = ALU_CONSTANTS;
1128
1129 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001130 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001131 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1132#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1133 /* Disable shadowing */
1134 *cmd++ = (0 << 24) | (1 << 16) | 0;
1135#else
1136 *cmd++ = (1 << 24) | (1 << 16) | 0;
1137#endif
1138 *cmd++ = TEX_CONSTANTS;
1139
1140 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001141 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001142 *cmd++ = (2 << 16) | 0;
1143
1144 /* the next BOOL_CONSTANT dwords is the shadow area for
1145 * boolean constants.
1146 */
1147 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1148 cmd += BOOL_CONSTANTS;
1149
1150 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001151 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001152 *cmd++ = (3 << 16) | 0;
1153
1154 /* the next LOOP_CONSTANTS dwords is the shadow area for
1155 * loop constants.
1156 */
1157 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1158 cmd += LOOP_CONSTANTS;
1159
1160 /* create indirect buffer command for above command sequence */
1161 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1162
1163 tmp_ctx.cmd = cmd;
1164}
1165
Jordan Crousea78c9172011-07-11 13:14:09 -06001166static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001167build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1168 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001169{
1170 unsigned int *cmd = tmp_ctx.cmd;
1171 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001172 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001173 unsigned int *partition1;
1174 unsigned int *shaderBases, *partition2;
1175
Jordan Crousea78c9172011-07-11 13:14:09 -06001176 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1177 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001178 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1179 + _shader_shadow_size(adreno_dev);
1180 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1181 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001182
1183 /* restore shader partitioning and instructions */
1184
1185 restore = cmd; /* start address */
1186
1187 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001188 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001189 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1190
1191 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001192 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001193 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1194
1195 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001196 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001197 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1198
Jordan Crousea78c9172011-07-11 13:14:09 -06001199 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001200 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001201 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1202 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1203
1204 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001205 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001206 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1207 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1208
1209 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001210 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001211 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1212 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001213
1214 /* create indirect buffer command for above command sequence */
1215 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1216
1217 /*
1218 * fixup SET_SHADER_BASES data
1219 *
1220 * since self-modifying PM4 code is being used here, a seperate
1221 * command buffer is used for this fixup operation, to ensure the
1222 * commands are not read by the PM4 engine before the data fields
1223 * have been written.
1224 */
1225
1226 fixup = cmd; /* start address */
1227
1228 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001229 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001230 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1231
1232 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001233 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001234 *cmd++ = REG_SCRATCH_REG2;
1235 /* AND off invalid bits. */
1236 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001237 /* OR in instruction memory size. */
1238 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001239
1240 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001241 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001242 *cmd++ = REG_SCRATCH_REG2;
1243 /* TBD #5: shader bases (to restore) */
1244 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1245
1246 /* create indirect buffer command for above command sequence */
1247 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1248
1249 /* save shader partitioning and instructions */
1250
1251 save = cmd; /* start address */
1252
Jordan Crouse084427d2011-07-28 08:37:58 -06001253 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001254 *cmd++ = 0;
1255
1256 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1257 * store the value in the data fields of the SET_CONSTANT commands
1258 * above.
1259 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001260 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001261 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1262 /* TBD #4a: partition info (to restore) */
1263 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001264 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001265 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1266 /* TBD #4b: partition info (to fixup) */
1267 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1268
Jordan Crousea78c9172011-07-11 13:14:09 -06001269
1270 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001271 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001272 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1273 /* TBD #1: start/size (to restore) */
1274 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1275
1276 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001277 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001278 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1279 /* TBD #2: start/size (to restore) */
1280 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1281
1282 /* store the shared shader instructions if vertex base is nonzero */
1283
Jordan Crouse084427d2011-07-28 08:37:58 -06001284 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001285 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1286 /* TBD #3: start/size (to restore) */
1287 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1288
Jordan Crousea78c9172011-07-11 13:14:09 -06001289
Jordan Crouse084427d2011-07-28 08:37:58 -06001290 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001291 *cmd++ = 0;
1292
1293 /* create indirect buffer command for above command sequence */
1294 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1295
1296 tmp_ctx.cmd = cmd;
1297}
1298
1299/* create buffers for saving/restoring registers, constants, & GMEM */
1300static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1301 struct adreno_context *drawctxt)
1302{
1303 int result;
1304
1305 /* Allocate vmalloc memory to store the gpustate */
1306 result = kgsl_allocate(&drawctxt->gpustate,
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001307 drawctxt->pagetable, _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001308
1309 if (result)
1310 return result;
1311
1312 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1313
1314 /* Blank out h/w register, constant, and command buffer shadows. */
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001315 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1316 _context_size(adreno_dev));
Jordan Crousea78c9172011-07-11 13:14:09 -06001317
1318 /* set-up command and vertex buffer pointers */
1319 tmp_ctx.cmd = tmp_ctx.start
1320 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1321
1322 /* build indirect command buffers to save & restore regs/constants */
1323 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1324 build_regrestore_cmds(adreno_dev, drawctxt);
1325 build_regsave_cmds(adreno_dev, drawctxt);
1326
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001327 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001328
1329 kgsl_cache_range_op(&drawctxt->gpustate,
1330 KGSL_CACHE_OP_FLUSH);
1331
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001332 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1333 drawctxt->gpustate.gpuaddr,
1334 drawctxt->gpustate.size, false);
Jordan Crousea78c9172011-07-11 13:14:09 -06001335 return 0;
1336}
1337
1338/* create buffers for saving/restoring registers, constants, & GMEM */
1339static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1340 struct adreno_context *drawctxt)
1341{
1342 int result;
1343
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001344 calc_gmemsize(&drawctxt->context_gmem_shadow,
1345 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001346 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1347
1348 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1349 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1350
1351 if (result)
1352 return result;
1353
1354 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1355 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1356
1357 /* blank out gmem shadow. */
1358 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1359 drawctxt->context_gmem_shadow.size);
1360
1361 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001362 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1363 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001364
1365 /* build TP0_CHICKEN register restore command buffer */
1366 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1367
1368 /* build indirect command buffers to save & restore gmem */
1369 /* Idle because we are reading PM override registers */
1370 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1371 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1372 tmp_ctx.cmd =
1373 build_gmem2sys_cmds(adreno_dev, drawctxt,
1374 &drawctxt->context_gmem_shadow);
1375 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1376 tmp_ctx.cmd =
1377 build_sys2gmem_cmds(adreno_dev, drawctxt,
1378 &drawctxt->context_gmem_shadow);
1379
1380 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1381 KGSL_CACHE_OP_FLUSH);
1382
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001383 kgsl_cffdump_syncmem(NULL,
1384 &drawctxt->context_gmem_shadow.gmemshadow,
1385 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1386 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1387
Jordan Crousea78c9172011-07-11 13:14:09 -06001388 return 0;
1389}
1390
1391static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1392 struct adreno_context *context)
1393{
1394 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001395 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001396
1397 if (context == NULL)
1398 return;
1399
1400 if (context->flags & CTXT_FLAGS_GPU_HANG)
1401 KGSL_CTXT_WARN(device,
1402 "Current active context has caused gpu hang\n");
1403
1404 KGSL_CTXT_INFO(device,
1405 "active context flags %08x\n", context->flags);
1406
1407 /* save registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001408 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1409 context->reg_save, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001410
1411 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1412 /* save shader partitioning and instructions. */
1413 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1414 context->shader_save, 3);
1415
1416 /* fixup shader partitioning parameter for
1417 * SET_SHADER_BASES.
1418 */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001419 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Jordan Crousea78c9172011-07-11 13:14:09 -06001420 context->shader_fixup, 3);
1421
1422 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1423 }
1424
1425 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1426 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1427 /* save gmem.
1428 * (note: changes shader. shader must already be saved.)
1429 */
1430 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1431 context->context_gmem_shadow.gmem_save, 3);
1432
1433 /* Restore TP0_CHICKEN */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001434 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Jordan Crousea78c9172011-07-11 13:14:09 -06001435 context->chicken_restore, 3);
1436
1437 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001438 } else if (adreno_is_a225(adreno_dev)) {
1439 unsigned int *cmds = &cmd[0];
1440 /*
1441 * Issue an empty draw call to avoid possible hangs due to
1442 * repeated idles without intervening draw calls.
1443 * On adreno 225 the PC block has a cache that is only
1444 * flushed on draw calls and repeated idles can make it
1445 * overflow. The gmem save path contains draw calls so
1446 * this workaround isn't needed there.
1447 */
1448 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1449 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1450 *cmds++ = 0;
1451 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1452 *cmds++ = 0;
1453 *cmds++ = 1<<14;
1454 *cmds++ = 0;
1455 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1456 *cmds++ = 0;
1457 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1458 *cmds++ = 0x00000000;
1459
1460 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1461 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001462 }
1463}
1464
1465static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1466 struct adreno_context *context)
1467{
1468 struct kgsl_device *device = &adreno_dev->dev;
1469 unsigned int cmds[5];
1470
1471 if (context == NULL) {
1472 /* No context - set the default apgetable and thats it */
1473 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1474 return;
1475 }
1476
1477 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1478
Jordan Crouse084427d2011-07-28 08:37:58 -06001479 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001480 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001481 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001482 cmds[3] = device->memstore.gpuaddr +
1483 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1484 cmds[4] = (unsigned int) context;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001485 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
Jordan Crousea78c9172011-07-11 13:14:09 -06001486 kgsl_mmu_setstate(device, context->pagetable);
1487
1488#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1489 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1490 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1491 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1492#endif
1493
1494 /* restore gmem.
1495 * (note: changes shader. shader must not already be restored.)
1496 */
1497 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1498 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1499 context->context_gmem_shadow.gmem_restore, 3);
1500
1501 /* Restore TP0_CHICKEN */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001502 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Jordan Crousea78c9172011-07-11 13:14:09 -06001503 context->chicken_restore, 3);
1504
1505 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1506 }
1507
1508 /* restore registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001509 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Jordan Crousea78c9172011-07-11 13:14:09 -06001510 context->reg_restore, 3);
1511
1512 /* restore shader instructions & partitioning. */
1513 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
Jordan Crousee0ea7622012-01-24 09:32:04 -07001514 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Jordan Crousea78c9172011-07-11 13:14:09 -06001515 context->shader_restore, 3);
1516 }
1517
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001518 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001519 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001520 cmds[1] = context->bin_base_offset;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001521 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1522 cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001523 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001524}
1525
1526/*
1527 * Interrupt management
1528 *
1529 * a2xx interrupt control is distributed among the various
1530 * hardware components (RB, CP, MMU). The main interrupt
1531 * tells us which component fired the interrupt, but one needs
1532 * to go to the individual component to find out why. The
1533 * following functions provide the broken out support for
1534 * managing the interrupts
1535 */
1536
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001537#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001538
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001539#define CP_INT_MASK \
1540 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001541 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1542 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1543 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1544 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001545 CP_INT_CNTL__IB1_INT_MASK | \
1546 CP_INT_CNTL__RB_INT_MASK)
1547
1548#define VALID_STATUS_COUNT_MAX 10
1549
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001550static struct {
1551 unsigned int mask;
1552 const char *message;
1553} kgsl_cp_error_irqs[] = {
1554 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1555 "ringbuffer TO packet in IB interrupt" },
1556 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1557 "ringbuffer opcode error interrupt" },
1558 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1559 "ringbuffer protected mode error interrupt" },
1560 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1561 "ringbuffer reserved bit error interrupt" },
1562 { CP_INT_CNTL__IB_ERROR_MASK,
1563 "ringbuffer IB error interrupt" },
1564};
1565
Jordan Crousea78c9172011-07-11 13:14:09 -06001566static void a2xx_cp_intrcallback(struct kgsl_device *device)
1567{
1568 unsigned int status = 0, num_reads = 0, master_status = 0;
1569 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1570 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001571 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001572
1573 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1574 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1575 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1576 adreno_regread(device, REG_CP_INT_STATUS, &status);
1577 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1578 &master_status);
1579 num_reads++;
1580 }
1581 if (num_reads > 1)
1582 KGSL_DRV_WARN(device,
1583 "Looped %d times to read REG_CP_INT_STATUS\n",
1584 num_reads);
Norman Geed7402ff2011-10-28 08:51:11 -06001585
1586 trace_kgsl_a2xx_irq_status(device, master_status, status);
1587
Jordan Crousea78c9172011-07-11 13:14:09 -06001588 if (!status) {
1589 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1590 /* This indicates that we could not read CP_INT_STAT.
1591 * As a precaution just wake up processes so
1592 * they can check their timestamps. Since, we
1593 * did not ack any interrupts this interrupt will
1594 * be generated again */
1595 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1596 wake_up_interruptible_all(&device->wait_queue);
1597 } else
1598 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1599 return;
1600 }
1601
1602 if (status & CP_INT_CNTL__RB_INT_MASK) {
1603 /* signal intr completion event */
1604 unsigned int enableflag = 0;
1605 kgsl_sharedmem_writel(&rb->device->memstore,
1606 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1607 enableflag);
1608 wmb();
1609 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1610 }
1611
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001612 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1613 if (status & kgsl_cp_error_irqs[i].mask) {
1614 KGSL_CMD_CRIT(rb->device, "%s\n",
1615 kgsl_cp_error_irqs[i].message);
1616 /*
1617 * on fatal errors, turn off the interrupts to
1618 * avoid storming. This has the side effect of
1619 * forcing a PM dump when the timestamp times out
1620 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001621
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001622 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1623 }
1624 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001625
1626 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001627 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001628 adreno_regwrite(device, REG_CP_INT_ACK, status);
1629
1630 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1631 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001632 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001633 wake_up_interruptible_all(&device->wait_queue);
1634 atomic_notifier_call_chain(&(device->ts_notifier_list),
1635 device->id,
1636 NULL);
1637 }
1638}
1639
1640static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1641{
1642 unsigned int status = 0;
1643 unsigned int rderr = 0;
1644
1645 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1646
1647 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1648 union rbbm_read_error_u rerr;
1649 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1650 rerr.val = rderr;
1651 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1652 rerr.f.read_error &&
1653 rerr.f.read_requester)
1654 KGSL_DRV_WARN(device,
1655 "rbbm read error interrupt: %08x\n", rderr);
1656 else
1657 KGSL_DRV_CRIT(device,
1658 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001659 }
1660
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001661 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001662 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1663}
1664
1665irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1666{
1667 struct kgsl_device *device = &adreno_dev->dev;
1668 irqreturn_t result = IRQ_NONE;
1669 unsigned int status;
1670
1671 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1672
1673 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1674 kgsl_mh_intrcallback(device);
1675 result = IRQ_HANDLED;
1676 }
1677
1678 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1679 a2xx_cp_intrcallback(device);
1680 result = IRQ_HANDLED;
1681 }
1682
1683 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1684 a2xx_rbbm_intrcallback(device);
1685 result = IRQ_HANDLED;
1686 }
1687
1688 return result;
1689}
1690
1691static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1692{
1693 struct kgsl_device *device = &adreno_dev->dev;
1694
1695 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001696 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1697 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001698 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1699 } else {
1700 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1701 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1702 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1703 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001704
1705 /* Force the writes to post before touching the IRQ line */
1706 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001707}
1708
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001709/* Defined in adreno_a2xx_snapshot.c */
1710void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
1711 int *remain, int hang);
1712
Jordan Crousea78c9172011-07-11 13:14:09 -06001713struct adreno_gpudev adreno_a2xx_gpudev = {
1714 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1715 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1716 .ctxt_save = a2xx_ctxt_save,
1717 .ctxt_restore = a2xx_ctxt_restore,
1718 .irq_handler = a2xx_irq_handler,
1719 .irq_control = a2xx_irq_control,
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001720 .snapshot = a2xx_snapshot,
Jordan Crousea78c9172011-07-11 13:14:09 -06001721};