blob: 5ce9cf85bc2ecf173156731b1ec7f18bd015598c [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
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700622 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
623 /* Store TP0_CHICKEN register */
624 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
625 *cmds++ = REG_TP0_CHICKEN;
Jordan Crousea78c9172011-07-11 13:14:09 -0600626
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700627 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600628
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700629 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
630 *cmds++ = 0;
631 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600632
633 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600634 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600635 *cmds++ = 0x00000000;
636
637 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600638 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600639 *cmds++ = 0x00000000;
640
641 /* program shader */
642
643 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600644 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600645 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
646 *cmds++ = 0;
647 /* valid(?) vtx constant flag & addr */
648 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
649 /* limit = 12 dwords */
650 *cmds++ = 0x00000030;
651
652 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600653 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600654 *cmds++ = 0x1;
655
Jordan Crouse084427d2011-07-28 08:37:58 -0600656 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600657 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600658 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
659 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
660 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
661
Jordan Crouse084427d2011-07-28 08:37:58 -0600662 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600663 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600664 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
665
Jordan Crouse084427d2011-07-28 08:37:58 -0600666 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600667 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600668 *cmds++ = 0x00000c20;
669
Tarun Karra16346b02011-07-24 15:04:26 -0700670 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600671 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700672 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700673
674 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600675 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700676 *cmds++ = 0x00003F00;
677
Jordan Crouse084427d2011-07-28 08:37:58 -0600678 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700679 *cmds++ = adreno_encode_istore_size(adreno_dev)
680 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700681
Jordan Crousea78c9172011-07-11 13:14:09 -0600682 /* load the patched vertex shader stream */
683 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
684
685 /* Load the patched fragment shader stream */
686 cmds =
687 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
688
689 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600690 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600691 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600692 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600693 *cmds++ = 0x10018001;
694 else
695 *cmds++ = 0x10010001;
696 *cmds++ = 0x00000008;
697
698 /* resolve */
699
700 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600701 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600702 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600703 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
704 *cmds++ = 0x00000b00;
705
706 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600707 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600708 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600709 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
710
711 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
712 * Base=gmem_base
713 */
714 /* gmem base assumed 4K aligned. */
715 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
716 *cmds++ =
717 (shadow->
718 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
719
720 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600721 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600722 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600723 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600724 *cmds++ = 0x08;
725 else
726 *cmds++ = 0;
727
728 /* set REG_PA_SU_SC_MODE_CNTL
729 * Front_ptype = draw triangles
730 * Back_ptype = draw triangles
731 * Provoking vertex = last
732 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600733 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600734 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600735 *cmds++ = 0x00080240;
736
737 /* Use maximum scissor values -- quad vertices already have the
738 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600739 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600740 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600741 *cmds++ = (0 << 16) | 0;
742 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600743 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600744 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600745 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
746 *cmds++ = (0x1fff << 16) | (0x1fff);
747
748 /* load the viewport so that z scale = clear depth and
749 * z offset = 0.0f
750 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600751 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600752 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600753 *cmds++ = 0xbf800000; /* -1.0f */
754 *cmds++ = 0x0;
755
Jordan Crouse084427d2011-07-28 08:37:58 -0600756 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600757 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600758 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
759
Jordan Crouse084427d2011-07-28 08:37:58 -0600760 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600761 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600762 *cmds++ = 0xffffffff;
763
Jordan Crouse084427d2011-07-28 08:37:58 -0600764 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600765 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600766 *cmds++ = 0x00000000;
767 *cmds++ = 0x00000000;
768
769 /* load the stencil ref value
770 * $AAM - do this later
771 */
772
773 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600774 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600775 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600776 *cmds++ = 0; /* RB_COPY_CONTROL */
777 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
778 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
779
780 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
781 * MaskWrite:R=G=B=A=1
782 */
783 *cmds++ = 0x0003c008 |
784 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
785 /* Make sure we stay in offsetx field. */
786 BUG_ON(offset & 0xfffff000);
787 *cmds++ = offset;
788
Jordan Crouse084427d2011-07-28 08:37:58 -0600789 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600790 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600791 *cmds++ = 0x6; /* EDRAM copy */
792
Jordan Crouse084427d2011-07-28 08:37:58 -0600793 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600794 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600795 *cmds++ = 0x00010000;
796
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600797 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600798 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600799 *cmds++ = 0;
800
Jordan Crouse084427d2011-07-28 08:37:58 -0600801 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700802 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600803 *cmds++ = 0x0000000;
804
Jordan Crouse084427d2011-07-28 08:37:58 -0600805 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600806 *cmds++ = 0; /* viz query info. */
807 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
808 *cmds++ = 0x00004088;
809 *cmds++ = 3; /* NumIndices=3 */
810 } else {
811 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600812 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600813 *cmds++ = 0; /* viz query info. */
814 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
815 *cmds++ = 0x00030088;
816 }
817
818 /* create indirect buffer command for above command sequence */
819 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
820
821 return cmds;
822}
823
824/* context restore */
825
826/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
827static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
828 struct adreno_context *drawctxt,
829 struct gmem_shadow_t *shadow)
830{
831 unsigned int *cmds = shadow->gmem_restore_commands;
832 unsigned int *start = cmds;
833
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700834 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
835 /* Store TP0_CHICKEN register */
836 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
837 *cmds++ = REG_TP0_CHICKEN;
838 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600839
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700840 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
841 *cmds++ = 0;
842 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600843
844 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600845 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600846 *cmds++ = 0x00000000;
847
848 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600849 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600850 *cmds++ = 0x00000000;
851 /* shader constants */
852
853 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600854 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600855
856 *cmds++ = (0x1 << 16) | (9 * 6);
857 /* valid(?) vtx constant flag & addr */
858 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
859 /* limit = 12 dwords */
860 *cmds++ = 0x00000030;
861 /* valid(?) vtx constant flag & addr */
862 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
863 /* limit = 8 dwords */
864 *cmds++ = 0x00000020;
865 *cmds++ = 0;
866 *cmds++ = 0;
867
868 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600869 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600870 *cmds++ = 0x1;
871
872 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
873
Tarun Karra16346b02011-07-24 15:04:26 -0700874 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600875 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700876 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700877
878 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600879 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700880 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
881
Jordan Crouse084427d2011-07-28 08:37:58 -0600882 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700883 *cmds++ = adreno_encode_istore_size(adreno_dev)
884 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700885
Jordan Crousea78c9172011-07-11 13:14:09 -0600886 /* Load the patched fragment shader stream */
887 cmds =
888 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
889
890 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600891 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600892 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600893 *cmds++ = 0x10030002;
894 *cmds++ = 0x00000008;
895
Jordan Crouse084427d2011-07-28 08:37:58 -0600896 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600897 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600898 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
899
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600900 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600901 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600902 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600903 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600904 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
905 }
906
907 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600908 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600909 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600910 *cmds++ = 0x00000c20;
911
Jordan Crouse084427d2011-07-28 08:37:58 -0600912 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600913 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600914 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
915 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
916 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
917
Jordan Crouse084427d2011-07-28 08:37:58 -0600918 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600919 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600920 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
921 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_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_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600925 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
926
Jordan Crouse084427d2011-07-28 08:37:58 -0600927 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600928 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600929 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
930
931 /* set REG_PA_SU_SC_MODE_CNTL
932 * Front_ptype = draw triangles
933 * Back_ptype = draw triangles
934 * Provoking vertex = last
935 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600936 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600937 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600938 *cmds++ = 0x00080240;
939
940 /* texture constants */
941 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600942 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600943 *cmds++ = (0x1 << 16) | (0 * 6);
944 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
945 cmds[0] |= (shadow->pitch >> 5) << 22;
946 cmds[1] |=
947 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
948 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
949 cmds += SYS2GMEM_TEX_CONST_LEN;
950
951 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600952 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600953 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600954 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
955
956 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
957 * Base=gmem_base
958 */
959 *cmds++ =
960 (shadow->
961 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
962
963 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600964 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600965 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600966
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600967 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600968 *cmds++ = 8; /* disable Z */
969 else
970 *cmds++ = 0; /* disable Z */
971
972 /* Use maximum scissor values -- quad vertices already
973 * have the correct bounds */
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_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600976 *cmds++ = (0 << 16) | 0;
977 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -0600978 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600979 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600980 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
981 *cmds++ = ((0x1fff) << 16) | 0x1fff;
982
Jordan Crouse084427d2011-07-28 08:37:58 -0600983 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600984 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600985 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
986 *cmds++ = 0x00000b00;
987
988 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -0600989 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600990 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600991 *cmds++ = 0xbf800000;
992 *cmds++ = 0x0;
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_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600996 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
997
Jordan Crouse084427d2011-07-28 08:37:58 -0600998 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600999 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001000 *cmds++ = 0xffffffff;
1001
Jordan Crouse084427d2011-07-28 08:37:58 -06001002 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001003 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -06001004 *cmds++ = 0x00000000;
1005 *cmds++ = 0x00000000;
1006
1007 /* load the stencil ref value
1008 * $AAM - do this later
1009 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001010 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001011 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001012 /* draw pixels with color and depth/stencil component */
1013 *cmds++ = 0x4;
1014
Jordan Crouse084427d2011-07-28 08:37:58 -06001015 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001016 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001017 *cmds++ = 0x00010000;
1018
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001019 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001020 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001021 *cmds++ = 0;
1022
Jordan Crouse084427d2011-07-28 08:37:58 -06001023 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001024 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001025 *cmds++ = 0x0000000;
1026
Jordan Crouse084427d2011-07-28 08:37:58 -06001027 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001028 *cmds++ = 0; /* viz query info. */
1029 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
1030 *cmds++ = 0x00004088;
1031 *cmds++ = 3; /* NumIndices=3 */
1032 } else {
1033 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -06001034 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001035 *cmds++ = 0; /* viz query info. */
1036 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
1037 *cmds++ = 0x00030088;
1038 }
1039
1040 /* create indirect buffer command for above command sequence */
1041 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
1042
1043 return cmds;
1044}
1045
Jordan Crousea78c9172011-07-11 13:14:09 -06001046static void build_regrestore_cmds(struct adreno_device *adreno_dev,
1047 struct adreno_context *drawctxt)
1048{
1049 unsigned int *start = tmp_ctx.cmd;
1050 unsigned int *cmd = start;
1051
1052 unsigned int i = 0;
1053 unsigned int reg_array_size = 0;
1054 const unsigned int *ptr_register_ranges;
1055
Jordan Crouse084427d2011-07-28 08:37:58 -06001056 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001057 *cmd++ = 0;
1058
1059 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -06001060 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -06001061 cmd++;
1062#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1063 /* Force mismatch */
1064 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1065#else
1066 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1067#endif
1068
1069 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -07001070 if (adreno_is_a220(adreno_dev)) {
1071 ptr_register_ranges = register_ranges_a220;
1072 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1073 } else if (adreno_is_a225(adreno_dev)) {
1074 ptr_register_ranges = register_ranges_a225;
1075 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001076 } else {
1077 ptr_register_ranges = register_ranges_a20x;
1078 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1079 }
1080
1081
1082 for (i = 0; i < (reg_array_size/2); i++) {
1083 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1084 ptr_register_ranges[i*2+1]);
1085 }
1086
1087 /* Now we know how many register blocks we have, we can compute command
1088 * length
1089 */
1090 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001091 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001092 /* Enable shadowing for the entire register block. */
1093#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1094 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1095#else
1096 start[4] |= (1 << 24) | (4 << 16);
1097#endif
1098
1099 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001100 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001101 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1102 *cmd++ = 0x00040400;
1103
Jordan Crouse084427d2011-07-28 08:37:58 -06001104 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001105 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001106 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001107 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1108 *cmd++ = 0x00000000;
1109
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001110 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001111 unsigned int i;
1112 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001113 for (i = REG_A220_VSC_BIN_SIZE; i <=
1114 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001115 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001116 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1117 &drawctxt->gpustate);
1118 *cmd++ = 0x00000000;
1119 j++;
1120 }
1121 }
1122
1123 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001124 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001125 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1126#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1127 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1128#else
1129 *cmd++ = (1 << 24) | (0 << 16) | 0;
1130#endif
1131 *cmd++ = ALU_CONSTANTS;
1132
1133 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001134 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001135 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1136#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1137 /* Disable shadowing */
1138 *cmd++ = (0 << 24) | (1 << 16) | 0;
1139#else
1140 *cmd++ = (1 << 24) | (1 << 16) | 0;
1141#endif
1142 *cmd++ = TEX_CONSTANTS;
1143
1144 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001145 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001146 *cmd++ = (2 << 16) | 0;
1147
1148 /* the next BOOL_CONSTANT dwords is the shadow area for
1149 * boolean constants.
1150 */
1151 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1152 cmd += BOOL_CONSTANTS;
1153
1154 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001155 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001156 *cmd++ = (3 << 16) | 0;
1157
1158 /* the next LOOP_CONSTANTS dwords is the shadow area for
1159 * loop constants.
1160 */
1161 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1162 cmd += LOOP_CONSTANTS;
1163
1164 /* create indirect buffer command for above command sequence */
1165 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1166
1167 tmp_ctx.cmd = cmd;
1168}
1169
Jordan Crousea78c9172011-07-11 13:14:09 -06001170static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001171build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1172 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001173{
1174 unsigned int *cmd = tmp_ctx.cmd;
1175 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001176 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001177 unsigned int *partition1;
1178 unsigned int *shaderBases, *partition2;
1179
Jordan Crousea78c9172011-07-11 13:14:09 -06001180 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1181 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001182 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1183 + _shader_shadow_size(adreno_dev);
1184 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1185 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001186
1187 /* restore shader partitioning and instructions */
1188
1189 restore = cmd; /* start address */
1190
1191 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001192 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001193 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1194
1195 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001196 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001197 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1198
1199 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001200 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001201 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1202
Jordan Crousea78c9172011-07-11 13:14:09 -06001203 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001204 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001205 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1206 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1207
1208 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001209 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001210 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1211 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1212
1213 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001214 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001215 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1216 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001217
1218 /* create indirect buffer command for above command sequence */
1219 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1220
1221 /*
1222 * fixup SET_SHADER_BASES data
1223 *
1224 * since self-modifying PM4 code is being used here, a seperate
1225 * command buffer is used for this fixup operation, to ensure the
1226 * commands are not read by the PM4 engine before the data fields
1227 * have been written.
1228 */
1229
1230 fixup = cmd; /* start address */
1231
1232 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001233 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001234 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1235
1236 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001237 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001238 *cmd++ = REG_SCRATCH_REG2;
1239 /* AND off invalid bits. */
1240 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001241 /* OR in instruction memory size. */
1242 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001243
1244 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001245 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001246 *cmd++ = REG_SCRATCH_REG2;
1247 /* TBD #5: shader bases (to restore) */
1248 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1249
1250 /* create indirect buffer command for above command sequence */
1251 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1252
1253 /* save shader partitioning and instructions */
1254
1255 save = cmd; /* start address */
1256
Jordan Crouse084427d2011-07-28 08:37:58 -06001257 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001258 *cmd++ = 0;
1259
1260 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1261 * store the value in the data fields of the SET_CONSTANT commands
1262 * above.
1263 */
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 #4a: partition info (to restore) */
1267 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001268 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001269 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1270 /* TBD #4b: partition info (to fixup) */
1271 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1272
Jordan Crousea78c9172011-07-11 13:14:09 -06001273
1274 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001275 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001276 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1277 /* TBD #1: start/size (to restore) */
1278 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1279
1280 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001281 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001282 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1283 /* TBD #2: start/size (to restore) */
1284 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1285
1286 /* store the shared shader instructions if vertex base is nonzero */
1287
Jordan Crouse084427d2011-07-28 08:37:58 -06001288 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001289 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1290 /* TBD #3: start/size (to restore) */
1291 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1292
Jordan Crousea78c9172011-07-11 13:14:09 -06001293
Jordan Crouse084427d2011-07-28 08:37:58 -06001294 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001295 *cmd++ = 0;
1296
1297 /* create indirect buffer command for above command sequence */
1298 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1299
1300 tmp_ctx.cmd = cmd;
1301}
1302
1303/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001304static int a2xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001305 struct adreno_context *drawctxt)
1306{
Jordan Crousea78c9172011-07-11 13:14:09 -06001307 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1308
Jordan Crousea78c9172011-07-11 13:14:09 -06001309 /* build indirect command buffers to save & restore regs/constants */
Jordan Crousea78c9172011-07-11 13:14:09 -06001310 build_regrestore_cmds(adreno_dev, drawctxt);
1311 build_regsave_cmds(adreno_dev, drawctxt);
1312
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001313 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001314
Jordan Crousea78c9172011-07-11 13:14:09 -06001315 return 0;
1316}
1317
1318/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001319static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001320 struct adreno_context *drawctxt)
1321{
1322 int result;
1323
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001324 calc_gmemsize(&drawctxt->context_gmem_shadow,
1325 adreno_dev->gmemspace.sizebytes);
Jordan Crousea78c9172011-07-11 13:14:09 -06001326 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1327
1328 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1329 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1330
1331 if (result)
1332 return result;
1333
1334 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1335 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1336
1337 /* blank out gmem shadow. */
1338 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1339 drawctxt->context_gmem_shadow.size);
1340
1341 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001342 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1343 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001344
1345 /* build TP0_CHICKEN register restore command buffer */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001346 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE))
1347 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001348
1349 /* build indirect command buffers to save & restore gmem */
Jordan Crousea78c9172011-07-11 13:14:09 -06001350 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1351 tmp_ctx.cmd =
1352 build_gmem2sys_cmds(adreno_dev, drawctxt,
1353 &drawctxt->context_gmem_shadow);
1354 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1355 tmp_ctx.cmd =
1356 build_sys2gmem_cmds(adreno_dev, drawctxt,
1357 &drawctxt->context_gmem_shadow);
1358
1359 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1360 KGSL_CACHE_OP_FLUSH);
1361
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001362 kgsl_cffdump_syncmem(NULL,
1363 &drawctxt->context_gmem_shadow.gmemshadow,
1364 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1365 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1366
Jordan Crousea78c9172011-07-11 13:14:09 -06001367 return 0;
1368}
1369
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001370static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
1371 struct adreno_context *drawctxt)
1372{
1373 int ret;
1374
1375 /*
1376 * Allocate memory for the GPU state and the context commands.
1377 * Despite the name, this is much more then just storage for
1378 * the gpustate. This contains command space for gmem save
1379 * and texture and vertex buffer storage too
1380 */
1381
1382 ret = kgsl_allocate(&drawctxt->gpustate,
1383 drawctxt->pagetable, _context_size(adreno_dev));
1384
1385 if (ret)
1386 return ret;
1387
1388 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1389 _context_size(adreno_dev));
1390
1391 tmp_ctx.cmd = tmp_ctx.start
1392 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1393
1394 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
1395 ret = a2xx_create_gpustate_shadow(adreno_dev, drawctxt);
1396 if (ret)
1397 goto done;
1398
1399 drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
1400 }
1401
1402 if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
1403 ret = a2xx_create_gmem_shadow(adreno_dev, drawctxt);
1404 if (ret)
1405 goto done;
1406 }
1407
1408 /* Flush and sync the gpustate memory */
1409
1410 kgsl_cache_range_op(&drawctxt->gpustate,
1411 KGSL_CACHE_OP_FLUSH);
1412
1413 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1414 drawctxt->gpustate.gpuaddr,
1415 drawctxt->gpustate.size, false);
1416
1417done:
1418 if (ret)
1419 kgsl_sharedmem_free(&drawctxt->gpustate);
1420
1421 return ret;
1422}
1423
1424static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001425 struct adreno_context *context)
1426{
1427 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001428 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001429
1430 if (context == NULL)
1431 return;
1432
1433 if (context->flags & CTXT_FLAGS_GPU_HANG)
1434 KGSL_CTXT_WARN(device,
1435 "Current active context has caused gpu hang\n");
1436
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001437 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001438
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001439 /* save registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001440 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001441 context->reg_save, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001442
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001443 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1444 /* save shader partitioning and instructions. */
1445 adreno_ringbuffer_issuecmds(device,
1446 KGSL_CMD_FLAGS_PMODE,
1447 context->shader_save, 3);
1448
1449 /*
1450 * fixup shader partitioning parameter for
1451 * SET_SHADER_BASES.
1452 */
1453 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1454 context->shader_fixup, 3);
1455
1456 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1457 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001458 }
1459
1460 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1461 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1462 /* save gmem.
1463 * (note: changes shader. shader must already be saved.)
1464 */
1465 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1466 context->context_gmem_shadow.gmem_save, 3);
1467
1468 /* Restore TP0_CHICKEN */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001469 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1470 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1471 context->chicken_restore, 3);
1472 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001473
1474 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001475 } else if (adreno_is_a225(adreno_dev)) {
1476 unsigned int *cmds = &cmd[0];
1477 /*
1478 * Issue an empty draw call to avoid possible hangs due to
1479 * repeated idles without intervening draw calls.
1480 * On adreno 225 the PC block has a cache that is only
1481 * flushed on draw calls and repeated idles can make it
1482 * overflow. The gmem save path contains draw calls so
1483 * this workaround isn't needed there.
1484 */
1485 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1486 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1487 *cmds++ = 0;
1488 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1489 *cmds++ = 0;
1490 *cmds++ = 1<<14;
1491 *cmds++ = 0;
1492 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1493 *cmds++ = 0;
1494 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1495 *cmds++ = 0x00000000;
1496
1497 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1498 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001499 }
1500}
1501
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001502static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001503 struct adreno_context *context)
1504{
1505 struct kgsl_device *device = &adreno_dev->dev;
1506 unsigned int cmds[5];
1507
1508 if (context == NULL) {
1509 /* No context - set the default apgetable and thats it */
1510 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1511 return;
1512 }
1513
1514 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1515
Jordan Crouse084427d2011-07-28 08:37:58 -06001516 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001517 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001518 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001519 cmds[3] = device->memstore.gpuaddr +
1520 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1521 cmds[4] = (unsigned int) context;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001522 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
Jordan Crousea78c9172011-07-11 13:14:09 -06001523 kgsl_mmu_setstate(device, context->pagetable);
1524
1525#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1526 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1527 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1528 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1529#endif
1530
1531 /* restore gmem.
1532 * (note: changes shader. shader must not already be restored.)
1533 */
1534 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1535 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1536 context->context_gmem_shadow.gmem_restore, 3);
1537
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001538 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1539 /* Restore TP0_CHICKEN */
1540 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1541 context->chicken_restore, 3);
1542 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001543
1544 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1545 }
1546
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001547 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001548
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001549 /* restore registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001550 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001551 context->reg_restore, 3);
1552
1553 /* restore shader instructions & partitioning. */
1554 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1555 adreno_ringbuffer_issuecmds(device,
1556 KGSL_CMD_FLAGS_NONE,
1557 context->shader_restore, 3);
1558 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001559 }
1560
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001561 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001562 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001563 cmds[1] = context->bin_base_offset;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001564 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1565 cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001566 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001567}
1568
1569/*
1570 * Interrupt management
1571 *
1572 * a2xx interrupt control is distributed among the various
1573 * hardware components (RB, CP, MMU). The main interrupt
1574 * tells us which component fired the interrupt, but one needs
1575 * to go to the individual component to find out why. The
1576 * following functions provide the broken out support for
1577 * managing the interrupts
1578 */
1579
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001580#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001581
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001582#define CP_INT_MASK \
1583 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001584 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1585 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1586 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1587 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001588 CP_INT_CNTL__IB1_INT_MASK | \
1589 CP_INT_CNTL__RB_INT_MASK)
1590
1591#define VALID_STATUS_COUNT_MAX 10
1592
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001593static struct {
1594 unsigned int mask;
1595 const char *message;
1596} kgsl_cp_error_irqs[] = {
1597 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1598 "ringbuffer TO packet in IB interrupt" },
1599 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1600 "ringbuffer opcode error interrupt" },
1601 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1602 "ringbuffer protected mode error interrupt" },
1603 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1604 "ringbuffer reserved bit error interrupt" },
1605 { CP_INT_CNTL__IB_ERROR_MASK,
1606 "ringbuffer IB error interrupt" },
1607};
1608
Jordan Crousea78c9172011-07-11 13:14:09 -06001609static void a2xx_cp_intrcallback(struct kgsl_device *device)
1610{
1611 unsigned int status = 0, num_reads = 0, master_status = 0;
1612 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1613 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001614 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001615
1616 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1617 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1618 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1619 adreno_regread(device, REG_CP_INT_STATUS, &status);
1620 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1621 &master_status);
1622 num_reads++;
1623 }
1624 if (num_reads > 1)
1625 KGSL_DRV_WARN(device,
1626 "Looped %d times to read REG_CP_INT_STATUS\n",
1627 num_reads);
Norman Geed7402ff2011-10-28 08:51:11 -06001628
1629 trace_kgsl_a2xx_irq_status(device, master_status, status);
1630
Jordan Crousea78c9172011-07-11 13:14:09 -06001631 if (!status) {
1632 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1633 /* This indicates that we could not read CP_INT_STAT.
1634 * As a precaution just wake up processes so
1635 * they can check their timestamps. Since, we
1636 * did not ack any interrupts this interrupt will
1637 * be generated again */
1638 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1639 wake_up_interruptible_all(&device->wait_queue);
1640 } else
1641 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1642 return;
1643 }
1644
1645 if (status & CP_INT_CNTL__RB_INT_MASK) {
1646 /* signal intr completion event */
1647 unsigned int enableflag = 0;
1648 kgsl_sharedmem_writel(&rb->device->memstore,
1649 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1650 enableflag);
1651 wmb();
1652 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1653 }
1654
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001655 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1656 if (status & kgsl_cp_error_irqs[i].mask) {
1657 KGSL_CMD_CRIT(rb->device, "%s\n",
1658 kgsl_cp_error_irqs[i].message);
1659 /*
1660 * on fatal errors, turn off the interrupts to
1661 * avoid storming. This has the side effect of
1662 * forcing a PM dump when the timestamp times out
1663 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001664
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001665 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1666 }
1667 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001668
1669 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001670 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001671 adreno_regwrite(device, REG_CP_INT_ACK, status);
1672
1673 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1674 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001675 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001676 wake_up_interruptible_all(&device->wait_queue);
1677 atomic_notifier_call_chain(&(device->ts_notifier_list),
1678 device->id,
1679 NULL);
1680 }
1681}
1682
1683static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1684{
1685 unsigned int status = 0;
1686 unsigned int rderr = 0;
1687
1688 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1689
1690 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1691 union rbbm_read_error_u rerr;
1692 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1693 rerr.val = rderr;
1694 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1695 rerr.f.read_error &&
1696 rerr.f.read_requester)
1697 KGSL_DRV_WARN(device,
1698 "rbbm read error interrupt: %08x\n", rderr);
1699 else
1700 KGSL_DRV_CRIT(device,
1701 "rbbm read error interrupt: %08x\n", rderr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001702 }
1703
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001704 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001705 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1706}
1707
1708irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1709{
1710 struct kgsl_device *device = &adreno_dev->dev;
1711 irqreturn_t result = IRQ_NONE;
1712 unsigned int status;
1713
1714 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1715
1716 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1717 kgsl_mh_intrcallback(device);
1718 result = IRQ_HANDLED;
1719 }
1720
1721 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1722 a2xx_cp_intrcallback(device);
1723 result = IRQ_HANDLED;
1724 }
1725
1726 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1727 a2xx_rbbm_intrcallback(device);
1728 result = IRQ_HANDLED;
1729 }
1730
1731 return result;
1732}
1733
1734static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1735{
1736 struct kgsl_device *device = &adreno_dev->dev;
1737
1738 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001739 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1740 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001741 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1742 } else {
1743 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1744 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1745 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1746 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001747
1748 /* Force the writes to post before touching the IRQ line */
1749 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001750}
1751
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001752/* Defined in adreno_a2xx_snapshot.c */
1753void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
1754 int *remain, int hang);
1755
Jordan Crousea78c9172011-07-11 13:14:09 -06001756struct adreno_gpudev adreno_a2xx_gpudev = {
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001757 .ctxt_create = a2xx_drawctxt_create,
1758 .ctxt_save = a2xx_drawctxt_save,
1759 .ctxt_restore = a2xx_drawctxt_restore,
Jordan Crousea78c9172011-07-11 13:14:09 -06001760 .irq_handler = a2xx_irq_handler,
1761 .irq_control = a2xx_irq_control,
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001762 .snapshot = a2xx_snapshot,
Jordan Crousea78c9172011-07-11 13:14:09 -06001763};