blob: 7ccfd3f87be4c00f44dfd488e5d3dedc0dbd806c [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
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070014#include <linux/delay.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070015#include <linux/sched.h>
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070016#include <mach/socinfo.h>
17
Jordan Crousea78c9172011-07-11 13:14:09 -060018#include "kgsl.h"
19#include "kgsl_sharedmem.h"
20#include "kgsl_cffdump.h"
21#include "adreno.h"
Norman Geed7402ff2011-10-28 08:51:11 -060022#include "adreno_a2xx_trace.h"
Jordan Crousea78c9172011-07-11 13:14:09 -060023
24/*
Jordan Crousef7597bf2012-01-03 08:43:34 -070025 * These are the registers that are dumped with GPU snapshot
26 * and postmortem. The lists are dword offset pairs in the
27 * form of {start offset, end offset} inclusive.
28 */
29
30/* A200, A205 */
31const unsigned int a200_registers[] = {
32 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
33 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
34 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
35 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
36 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
37 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
38 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
39 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
40 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
41 0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
42 0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
43 0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
44 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
45 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
46 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
47 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
48 0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
49 0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
50 0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
51 0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
52 0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
53 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
54 0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
55 0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
56 0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
57};
58
Jordan Crousef7597bf2012-01-03 08:43:34 -070059const unsigned int a220_registers[] = {
60 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
61 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
62 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
63 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
64 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
65 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
66 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
67 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
68 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
69 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
70 0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
71 0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
72 0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
73 0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
74 0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
75 0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
76 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
77 0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
78 0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
79 0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
80 0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
81 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
82 0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
83 0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
84 0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
85 0x4900, 0x4900, 0x4908, 0x4908,
86};
87
Jeremy Gebben6be78d12012-03-07 16:02:47 -070088const unsigned int a225_registers[] = {
89 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
90 0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1,
91 0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA,
92 0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392,
93 0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB,
94 0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F,
95 0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587,
96 0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609,
97 0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31,
98 0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F,
99 0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C,
100 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06,
101 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
102 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
103 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
104 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082,
105 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7,
106 0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222,
107 0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A,
108 0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326,
109 0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F,
110 0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584,
111 0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610,
112 0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697,
113 0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D,
114 0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783,
115 0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900,
116 0x4908, 0x4908,
117};
118
Jordan Crousef7597bf2012-01-03 08:43:34 -0700119const unsigned int a200_registers_count = ARRAY_SIZE(a200_registers) / 2;
120const unsigned int a220_registers_count = ARRAY_SIZE(a220_registers) / 2;
Jeremy Gebben6be78d12012-03-07 16:02:47 -0700121const unsigned int a225_registers_count = ARRAY_SIZE(a225_registers) / 2;
Jordan Crousef7597bf2012-01-03 08:43:34 -0700122
123/*
Jordan Crousea78c9172011-07-11 13:14:09 -0600124 *
125 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
126 * (34.5KB)
127 *
128 * +---------------------+------------+-------------+---+---------------------+
129 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
130 * +---------------------+------------+-------------+---+---------------------+
131 * ________________________________/ \____________________
132 * / |
133 * +--------------+-----------+------+-----------+------------------------+
134 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
135 * +--------------+-----------+------+-----------+------------------------+
136 *
137 * 8K - ALU Constant Shadow (8K aligned)
138 * 4K - H/W Register Shadow (8K aligned)
139 * 4K - Command and Vertex Buffers
140 * - Indirect command buffer : Const/Reg restore
141 * - includes Loop & Bool const shadows
142 * - Indirect command buffer : Const/Reg save
143 * - Quad vertices & texture coordinates
144 * - Indirect command buffer : Gmem save
145 * - Indirect command buffer : Gmem restore
146 * - Unused (padding to 8KB boundary)
147 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
148 * 18K - Shader Instruction Shadow
149 * - 6K vertex (32 byte aligned)
150 * - 6K pixel (32 byte aligned)
151 * - 6K shared (32 byte aligned)
152 *
153 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
154 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
155 * 16 bytes per constant. If the texture constants were transfered this way,
156 * the Command & Vertex Buffers section would extend past the 16K boundary.
157 * By moving the texture constant shadow area to start at 16KB boundary, we
158 * only require approximately 40 bytes more memory, but are able to use the
159 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
160 * context switching.
161 *
162 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
163 * constants would require an additional 8KB each, for alignment.]
164 *
165 */
166
167/* Constants */
168
169#define ALU_CONSTANTS 2048 /* DWORDS */
170#define NUM_REGISTERS 1024 /* DWORDS */
171#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
172#define CMD_BUFFER_LEN 9216 /* DWORDS */
173#else
174#define CMD_BUFFER_LEN 3072 /* DWORDS */
175#endif
176#define TEX_CONSTANTS (32*6) /* DWORDS */
177#define BOOL_CONSTANTS 8 /* DWORDS */
178#define LOOP_CONSTANTS 56 /* DWORDS */
Jordan Crousea78c9172011-07-11 13:14:09 -0600179
180/* LOAD_CONSTANT_CONTEXT shadow size */
181#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
182
183#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
184#define REG_SHADOW_SIZE 0x1000 /* 4KB */
185#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
186#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
187#else
188#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
189#endif
190#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
Jordan Crousea78c9172011-07-11 13:14:09 -0600191
192#define REG_OFFSET LCC_SHADOW_SIZE
193#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
194#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
195#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
196
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700197static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
198{
Jordan Crousec6b3a992012-02-04 10:23:51 -0700199 return adreno_dev->istore_size *
200 (adreno_dev->instruction_size * sizeof(unsigned int));
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700201}
202
203static inline int _context_size(struct adreno_device *adreno_dev)
204{
205 return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
206}
Jordan Crousea78c9172011-07-11 13:14:09 -0600207
208/* A scratchpad used to build commands during context create */
209
210static struct tmp_ctx {
211 unsigned int *start; /* Command & Vertex buffer start */
212 unsigned int *cmd; /* Next available dword in C&V buffer */
213
214 /* address of buffers, needed when creating IB1 command buffers. */
215 uint32_t bool_shadow; /* bool constants */
216 uint32_t loop_shadow; /* loop constants */
217
Jordan Crousea78c9172011-07-11 13:14:09 -0600218 uint32_t shader_shared; /* shared shader instruction shadow */
219 uint32_t shader_vertex; /* vertex shader instruction shadow */
220 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600221
222 /* Addresses in command buffer where separately handled registers
223 * are saved
224 */
225 uint32_t reg_values[33];
226 uint32_t chicken_restore;
227
228 uint32_t gmem_base; /* Base gpu address of GMEM */
229
230} tmp_ctx;
231
232/* context save (gmem -> sys) */
233
234/* pre-compiled vertex shader program
235*
236* attribute vec4 P;
237* void main(void)
238* {
239* gl_Position = P;
240* }
241*/
242#define GMEM2SYS_VTX_PGM_LEN 0x12
243
244static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
245 0x00011003, 0x00001000, 0xc2000000,
246 0x00001004, 0x00001000, 0xc4000000,
247 0x00001005, 0x00002000, 0x00000000,
248 0x1cb81000, 0x00398a88, 0x00000003,
249 0x140f803e, 0x00000000, 0xe2010100,
250 0x14000000, 0x00000000, 0xe2000000
251};
252
253/* pre-compiled fragment shader program
254*
255* precision highp float;
256* uniform vec4 clear_color;
257* void main(void)
258* {
259* gl_FragColor = clear_color;
260* }
261*/
262
263#define GMEM2SYS_FRAG_PGM_LEN 0x0c
264
265static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
266 0x00000000, 0x1002c400, 0x10000000,
267 0x00001003, 0x00002000, 0x00000000,
268 0x140f8000, 0x00000000, 0x22000000,
269 0x14000000, 0x00000000, 0xe2000000
270};
271
272/* context restore (sys -> gmem) */
273/* pre-compiled vertex shader program
274*
275* attribute vec4 position;
276* attribute vec4 texcoord;
277* varying vec4 texcoord0;
278* void main()
279* {
280* gl_Position = position;
281* texcoord0 = texcoord;
282* }
283*/
284
285#define SYS2GMEM_VTX_PGM_LEN 0x18
286
287static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
288 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
289 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
290 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
291 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
292 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
293 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
294};
295
296/* pre-compiled fragment shader program
297*
298* precision mediump float;
299* uniform sampler2D tex0;
300* varying vec4 texcoord0;
301* void main()
302* {
303* gl_FragColor = texture2D(tex0, texcoord0.xy);
304* }
305*/
306
307#define SYS2GMEM_FRAG_PGM_LEN 0x0f
308
309static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
310 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
311 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
312 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
313 0x14000000, 0x00000000, 0xe2000000
314};
315
316/* shader texture constants (sysmem -> gmem) */
317#define SYS2GMEM_TEX_CONST_LEN 6
318
319static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
320 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
321 * RFMode=ZeroClamp-1, Dim=1:2d
322 */
323 0x00000002, /* Pitch = TBD */
324
325 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
326 * NearestClamp=1:OGL Mode
327 */
328 0x00000800, /* Address[31:12] = TBD */
329
330 /* Width, Height, EndianSwap=0:None */
331 0, /* Width & Height = TBD */
332
333 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
334 * Mip=2:BaseMap
335 */
336 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
337
338 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
339 * Dim3d=0
340 */
341 0,
342
343 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
344 * Dim=1:2d, MipPacking=0
345 */
346 1 << 9 /* Mip Address[31:12] = TBD */
347};
348
Jordan Crousea78c9172011-07-11 13:14:09 -0600349#define NUM_COLOR_FORMATS 13
350
351static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
352 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
353 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
354 FMT_5_6_5, /* COLORX_5_6_5 */
355 FMT_8, /* COLORX_8 */
356 FMT_8_8, /* COLORX_8_8 */
357 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
358 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
359 FMT_16_FLOAT, /* COLORX_16_FLOAT */
360 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
361 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
362 FMT_32_FLOAT, /* COLORX_32_FLOAT */
363 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
364 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
365};
366
367static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
368 2, /* COLORX_4_4_4_4 */
369 2, /* COLORX_1_5_5_5 */
370 2, /* COLORX_5_6_5 */
371 1, /* COLORX_8 */
372 2, /* COLORX_8_8 8*/
373 4, /* COLORX_8_8_8_8 */
374 4, /* COLORX_S8_8_8_8 */
375 2, /* COLORX_16_FLOAT */
376 4, /* COLORX_16_16_FLOAT */
377 8, /* COLORX_16_16_16_16_FLOAT */
378 4, /* COLORX_32_FLOAT */
379 8, /* COLORX_32_32_FLOAT */
380 16, /* COLORX_32_32_32_32_FLOAT */
381};
382
383/* shader linkage info */
384#define SHADER_CONST_ADDR (11 * 6 + 3)
385
Jordan Crousea78c9172011-07-11 13:14:09 -0600386
387static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
388 unsigned int *shader_pgm, int dwords)
389{
390 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600391 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600392 /* 0=vertex shader, 1=fragment shader */
393 *cmds++ = vtxfrag;
394 /* instruction start & size (in 32-bit words) */
395 *cmds++ = ((0 << 16) | dwords);
396
397 memcpy(cmds, shader_pgm, dwords << 2);
398 cmds += dwords;
399
400 return cmds;
401}
402
403static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
404 uint32_t src, int dwords)
405{
406 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600407 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600408 *cmds++ = src++;
409 *cmds++ = dst;
410 dst += 4;
411 }
412
413 return cmds;
414}
415
416#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
417
418static void build_reg_to_mem_range(unsigned int start, unsigned int end,
419 unsigned int **cmd,
420 struct adreno_context *drawctxt)
421{
422 unsigned int i = start;
423
424 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600425 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600426 *(*cmd)++ = i;
427 *(*cmd)++ =
428 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
429 (i - 0x2000) * 4;
430 }
431}
432
433#endif
434
435/* chicken restore */
436static unsigned int *build_chicken_restore_cmds(
437 struct adreno_context *drawctxt)
438{
439 unsigned int *start = tmp_ctx.cmd;
440 unsigned int *cmds = start;
441
Jordan Crouse084427d2011-07-28 08:37:58 -0600442 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600443 *cmds++ = 0;
444
Jordan Crouse084427d2011-07-28 08:37:58 -0600445 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600446 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
447 *cmds++ = 0x00000000;
448
449 /* create indirect buffer command for above command sequence */
450 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
451
452 return cmds;
453}
454
455/****************************************************************************/
456/* context save */
457/****************************************************************************/
458
459static const unsigned int register_ranges_a20x[] = {
460 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
461 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
462 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
463 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
464 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
465 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
466 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
467 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
468 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
469 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
470 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
471 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
472 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
473 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
474};
475
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700476static const unsigned int register_ranges_a220[] = {
Jordan Crousea78c9172011-07-11 13:14:09 -0600477 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
478 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
479 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
480 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
481 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
482 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
483 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
484 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
485 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700486 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600487 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
488 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
489 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
490 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
491 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700492 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
493 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600494 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
495};
496
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700497static const unsigned int register_ranges_a225[] = {
498 REG_RB_SURFACE_INFO, REG_A225_RB_COLOR_INFO3,
499 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
500 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
501 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
502 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
503 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
504 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
505 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
506 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
507 REG_A220_PC_MAX_VTX_INDX, REG_A225_PC_MULTI_PRIM_IB_RESET_INDX,
508 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
509 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
510 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
511 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
512 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
513 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
514 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
515 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
Jeremy Gebbene139a042011-11-17 16:20:41 -0700516 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
517 REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700518};
519
Jordan Crousea78c9172011-07-11 13:14:09 -0600520
521/* save h/w regs, alu constants, texture contants, etc. ...
522* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
523*/
524static void build_regsave_cmds(struct adreno_device *adreno_dev,
525 struct adreno_context *drawctxt)
526{
527 unsigned int *start = tmp_ctx.cmd;
528 unsigned int *cmd = start;
529
Jordan Crouse084427d2011-07-28 08:37:58 -0600530 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600531 *cmd++ = 0;
532
533#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
534 /* Make sure the HW context has the correct register values
535 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600536 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600537 *cmd++ = 0;
538
539 {
540 unsigned int i = 0;
541 unsigned int reg_array_size = 0;
542 const unsigned int *ptr_register_ranges;
543
544 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700545 if (adreno_is_a220(adreno_dev)) {
546 ptr_register_ranges = register_ranges_a220;
547 reg_array_size = ARRAY_SIZE(register_ranges_a220);
548 } else if (adreno_is_a225(adreno_dev)) {
549 ptr_register_ranges = register_ranges_a225;
550 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600551 } else {
552 ptr_register_ranges = register_ranges_a20x;
553 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
554 }
555
556
557 /* Write HW registers into shadow */
558 for (i = 0; i < (reg_array_size/2) ; i++) {
559 build_reg_to_mem_range(ptr_register_ranges[i*2],
560 ptr_register_ranges[i*2+1],
561 &cmd, drawctxt);
562 }
563 }
564
565 /* Copy ALU constants */
566 cmd =
567 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
568 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
569
570 /* Copy Tex constants */
571 cmd =
572 reg_to_mem(cmd,
573 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
574 REG_SQ_FETCH_0, TEX_CONSTANTS);
575#else
576
577 /* Insert a wait for idle packet before reading the registers.
578 * This is to fix a hang/reset seen during stress testing. In this
579 * hang, CP encountered a timeout reading SQ's boolean constant
580 * register. There is logic in the HW that blocks reading of this
581 * register when the SQ block is not idle, which we believe is
582 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600583 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600584 *cmd++ = 0;
585
586 /* H/w registers are already shadowed; just need to disable shadowing
587 * to prevent corruption.
588 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600589 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600590 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
591 *cmd++ = 4 << 16; /* regs, start=0 */
592 *cmd++ = 0x0; /* count = 0 */
593
594 /* ALU constants are already shadowed; just need to disable shadowing
595 * to prevent corruption.
596 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600597 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600598 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
599 *cmd++ = 0 << 16; /* ALU, start=0 */
600 *cmd++ = 0x0; /* count = 0 */
601
602 /* Tex constants are already shadowed; just need to disable shadowing
603 * to prevent corruption.
604 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600605 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600606 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
607 *cmd++ = 1 << 16; /* Tex, start=0 */
608 *cmd++ = 0x0; /* count = 0 */
609#endif
610
611 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600612 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600613 *cmd++ = REG_SQ_GPR_MANAGEMENT;
614 *cmd++ = tmp_ctx.reg_values[0];
615
Jordan Crouse084427d2011-07-28 08:37:58 -0600616 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600617 *cmd++ = REG_TP0_CHICKEN;
618 *cmd++ = tmp_ctx.reg_values[1];
619
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600620 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600621 unsigned int i;
622 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700623 for (i = REG_A220_VSC_BIN_SIZE; i <=
624 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600625 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600626 *cmd++ = i;
627 *cmd++ = tmp_ctx.reg_values[j];
628 j++;
629 }
630 }
631
632 /* Copy Boolean constants */
633 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
634 BOOL_CONSTANTS);
635
636 /* Copy Loop constants */
637 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
638 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
639
640 /* create indirect buffer command for above command sequence */
641 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
642
643 tmp_ctx.cmd = cmd;
644}
645
646/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
647static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
648 struct adreno_context *drawctxt,
649 struct gmem_shadow_t *shadow)
650{
651 unsigned int *cmds = shadow->gmem_save_commands;
652 unsigned int *start = cmds;
653 /* Calculate the new offset based on the adjusted base */
654 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
655 unsigned int addr = shadow->gmemshadow.gpuaddr;
656 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
657
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700658 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
659 /* Store TP0_CHICKEN register */
660 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
661 *cmds++ = REG_TP0_CHICKEN;
Jordan Crousea78c9172011-07-11 13:14:09 -0600662
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700663 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600664
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700665 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
666 *cmds++ = 0;
667 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600668
669 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600670 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600671 *cmds++ = 0x00000000;
672
673 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600674 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600675 *cmds++ = 0x00000000;
676
677 /* program shader */
678
679 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600680 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600681 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
682 *cmds++ = 0;
683 /* valid(?) vtx constant flag & addr */
684 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
685 /* limit = 12 dwords */
686 *cmds++ = 0x00000030;
687
688 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600689 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600690 *cmds++ = 0x1;
691
Jordan Crouse084427d2011-07-28 08:37:58 -0600692 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600693 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600694 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
695 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
696 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
697
Jordan Crouse084427d2011-07-28 08:37:58 -0600698 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600699 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600700 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
701
Jordan Crouse084427d2011-07-28 08:37:58 -0600702 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600703 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600704 *cmds++ = 0x00000c20;
705
Tarun Karra16346b02011-07-24 15:04:26 -0700706 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600707 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700708 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700709
710 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600711 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700712 *cmds++ = 0x00003F00;
713
Jordan Crouse084427d2011-07-28 08:37:58 -0600714 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700715 *cmds++ = adreno_encode_istore_size(adreno_dev)
716 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700717
Jordan Crousea78c9172011-07-11 13:14:09 -0600718 /* load the patched vertex shader stream */
719 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
720
721 /* Load the patched fragment shader stream */
722 cmds =
723 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
724
725 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600726 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600727 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600728 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600729 *cmds++ = 0x10018001;
730 else
731 *cmds++ = 0x10010001;
732 *cmds++ = 0x00000008;
733
734 /* resolve */
735
736 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600737 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600738 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600739 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
740 *cmds++ = 0x00000b00;
741
742 /* program surface info */
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_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600745 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
746
747 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
748 * Base=gmem_base
749 */
750 /* gmem base assumed 4K aligned. */
751 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
752 *cmds++ =
753 (shadow->
754 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
755
756 /* disable Z */
Jordan Crouse084427d2011-07-28 08:37:58 -0600757 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600758 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600759 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600760 *cmds++ = 0x08;
761 else
762 *cmds++ = 0;
763
764 /* set REG_PA_SU_SC_MODE_CNTL
765 * Front_ptype = draw triangles
766 * Back_ptype = draw triangles
767 * Provoking vertex = last
768 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600769 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600770 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600771 *cmds++ = 0x00080240;
772
773 /* Use maximum scissor values -- quad vertices already have the
774 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600775 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600776 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600777 *cmds++ = (0 << 16) | 0;
778 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600779 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600780 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600781 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
782 *cmds++ = (0x1fff << 16) | (0x1fff);
783
784 /* load the viewport so that z scale = clear depth and
785 * z offset = 0.0f
786 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600787 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600788 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600789 *cmds++ = 0xbf800000; /* -1.0f */
790 *cmds++ = 0x0;
791
Jordan Crouse084427d2011-07-28 08:37:58 -0600792 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600793 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600794 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
795
Jordan Crouse084427d2011-07-28 08:37:58 -0600796 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600797 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600798 *cmds++ = 0xffffffff;
799
Jordan Crouse084427d2011-07-28 08:37:58 -0600800 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600801 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600802 *cmds++ = 0x00000000;
803 *cmds++ = 0x00000000;
804
805 /* load the stencil ref value
806 * $AAM - do this later
807 */
808
809 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600810 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600811 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600812 *cmds++ = 0; /* RB_COPY_CONTROL */
813 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
814 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
815
816 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
817 * MaskWrite:R=G=B=A=1
818 */
819 *cmds++ = 0x0003c008 |
820 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
821 /* Make sure we stay in offsetx field. */
822 BUG_ON(offset & 0xfffff000);
823 *cmds++ = offset;
824
Jordan Crouse084427d2011-07-28 08:37:58 -0600825 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600826 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600827 *cmds++ = 0x6; /* EDRAM copy */
828
Jordan Crouse084427d2011-07-28 08:37:58 -0600829 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600830 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600831 *cmds++ = 0x00010000;
832
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600833 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600834 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700835 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600836 *cmds++ = 0x0000000;
837
Jordan Crouse084427d2011-07-28 08:37:58 -0600838 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600839 *cmds++ = 0; /* viz query info. */
840 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
841 *cmds++ = 0x00004088;
842 *cmds++ = 3; /* NumIndices=3 */
843 } else {
844 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600845 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600846 *cmds++ = 0; /* viz query info. */
847 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
848 *cmds++ = 0x00030088;
849 }
850
851 /* create indirect buffer command for above command sequence */
852 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
853
854 return cmds;
855}
856
857/* context restore */
858
859/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
860static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
861 struct adreno_context *drawctxt,
862 struct gmem_shadow_t *shadow)
863{
864 unsigned int *cmds = shadow->gmem_restore_commands;
865 unsigned int *start = cmds;
866
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700867 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
868 /* Store TP0_CHICKEN register */
869 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
870 *cmds++ = REG_TP0_CHICKEN;
871 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600872
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700873 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
874 *cmds++ = 0;
875 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600876
877 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600878 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600879 *cmds++ = 0x00000000;
880
881 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600882 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600883 *cmds++ = 0x00000000;
884 /* shader constants */
885
886 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600887 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600888
889 *cmds++ = (0x1 << 16) | (9 * 6);
890 /* valid(?) vtx constant flag & addr */
891 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
892 /* limit = 12 dwords */
893 *cmds++ = 0x00000030;
894 /* valid(?) vtx constant flag & addr */
895 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
896 /* limit = 8 dwords */
897 *cmds++ = 0x00000020;
898 *cmds++ = 0;
899 *cmds++ = 0;
900
901 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600902 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600903 *cmds++ = 0x1;
904
905 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
906
Tarun Karra16346b02011-07-24 15:04:26 -0700907 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600908 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700909 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700910
911 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600912 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700913 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
914
Jordan Crouse084427d2011-07-28 08:37:58 -0600915 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700916 *cmds++ = adreno_encode_istore_size(adreno_dev)
917 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700918
Jordan Crousea78c9172011-07-11 13:14:09 -0600919 /* Load the patched fragment shader stream */
920 cmds =
921 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
922
923 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600924 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600925 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600926 *cmds++ = 0x10030002;
927 *cmds++ = 0x00000008;
928
Jordan Crouse084427d2011-07-28 08:37:58 -0600929 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600930 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600931 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
932
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600933 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600934 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600935 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600936 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600937 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
938 }
939
940 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600941 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600942 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600943 *cmds++ = 0x00000c20;
944
Jordan Crouse084427d2011-07-28 08:37:58 -0600945 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600946 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600947 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
948 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
949 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
950
Jordan Crouse084427d2011-07-28 08:37:58 -0600951 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600952 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600953 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
954 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
955
Jordan Crouse084427d2011-07-28 08:37:58 -0600956 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600957 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600958 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
959
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_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600962 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
963
964 /* set REG_PA_SU_SC_MODE_CNTL
965 * Front_ptype = draw triangles
966 * Back_ptype = draw triangles
967 * Provoking vertex = last
968 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600969 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600970 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600971 *cmds++ = 0x00080240;
972
973 /* texture constants */
974 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600975 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600976 *cmds++ = (0x1 << 16) | (0 * 6);
977 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
978 cmds[0] |= (shadow->pitch >> 5) << 22;
979 cmds[1] |=
980 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
981 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
982 cmds += SYS2GMEM_TEX_CONST_LEN;
983
984 /* program surface info */
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_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600987 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
988
989 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
990 * Base=gmem_base
991 */
992 *cmds++ =
993 (shadow->
994 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
995
996 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600997 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600998 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600999
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001000 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -06001001 *cmds++ = 8; /* disable Z */
1002 else
1003 *cmds++ = 0; /* disable Z */
1004
1005 /* Use maximum scissor values -- quad vertices already
1006 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -06001007 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001008 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001009 *cmds++ = (0 << 16) | 0;
1010 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -06001011 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001012 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001013 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
1014 *cmds++ = ((0x1fff) << 16) | 0x1fff;
1015
Jordan Crouse084427d2011-07-28 08:37:58 -06001016 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001017 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001018 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
1019 *cmds++ = 0x00000b00;
1020
1021 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -06001022 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001023 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -06001024 *cmds++ = 0xbf800000;
1025 *cmds++ = 0x0;
1026
Jordan Crouse084427d2011-07-28 08:37:58 -06001027 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001028 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001029 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
1030
Jordan Crouse084427d2011-07-28 08:37:58 -06001031 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001032 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001033 *cmds++ = 0xffffffff;
1034
Jordan Crouse084427d2011-07-28 08:37:58 -06001035 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001036 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -06001037 *cmds++ = 0x00000000;
1038 *cmds++ = 0x00000000;
1039
1040 /* load the stencil ref value
1041 * $AAM - do this later
1042 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001043 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001044 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001045 /* draw pixels with color and depth/stencil component */
1046 *cmds++ = 0x4;
1047
Jordan Crouse084427d2011-07-28 08:37:58 -06001048 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001049 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001050 *cmds++ = 0x00010000;
1051
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001052 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001053 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001054 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001055 *cmds++ = 0x0000000;
1056
Jordan Crouse084427d2011-07-28 08:37:58 -06001057 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001058 *cmds++ = 0; /* viz query info. */
1059 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
1060 *cmds++ = 0x00004088;
1061 *cmds++ = 3; /* NumIndices=3 */
1062 } else {
1063 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -06001064 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001065 *cmds++ = 0; /* viz query info. */
1066 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
1067 *cmds++ = 0x00030088;
1068 }
1069
1070 /* create indirect buffer command for above command sequence */
1071 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
1072
1073 return cmds;
1074}
1075
Jordan Crousea78c9172011-07-11 13:14:09 -06001076static void build_regrestore_cmds(struct adreno_device *adreno_dev,
1077 struct adreno_context *drawctxt)
1078{
1079 unsigned int *start = tmp_ctx.cmd;
1080 unsigned int *cmd = start;
1081
1082 unsigned int i = 0;
1083 unsigned int reg_array_size = 0;
1084 const unsigned int *ptr_register_ranges;
1085
Jordan Crouse084427d2011-07-28 08:37:58 -06001086 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001087 *cmd++ = 0;
1088
1089 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -06001090 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -06001091 cmd++;
1092#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1093 /* Force mismatch */
1094 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1095#else
1096 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1097#endif
1098
1099 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -07001100 if (adreno_is_a220(adreno_dev)) {
1101 ptr_register_ranges = register_ranges_a220;
1102 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1103 } else if (adreno_is_a225(adreno_dev)) {
1104 ptr_register_ranges = register_ranges_a225;
1105 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001106 } else {
1107 ptr_register_ranges = register_ranges_a20x;
1108 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1109 }
1110
1111
1112 for (i = 0; i < (reg_array_size/2); i++) {
1113 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1114 ptr_register_ranges[i*2+1]);
1115 }
1116
1117 /* Now we know how many register blocks we have, we can compute command
1118 * length
1119 */
1120 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001121 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001122 /* Enable shadowing for the entire register block. */
1123#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1124 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1125#else
1126 start[4] |= (1 << 24) | (4 << 16);
1127#endif
1128
1129 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001130 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001131 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1132 *cmd++ = 0x00040400;
1133
Jordan Crouse084427d2011-07-28 08:37:58 -06001134 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001135 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001136 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001137 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1138 *cmd++ = 0x00000000;
1139
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001140 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001141 unsigned int i;
1142 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001143 for (i = REG_A220_VSC_BIN_SIZE; i <=
1144 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001145 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001146 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1147 &drawctxt->gpustate);
1148 *cmd++ = 0x00000000;
1149 j++;
1150 }
1151 }
1152
1153 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001154 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001155 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1156#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1157 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1158#else
1159 *cmd++ = (1 << 24) | (0 << 16) | 0;
1160#endif
1161 *cmd++ = ALU_CONSTANTS;
1162
1163 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001164 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001165 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1166#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1167 /* Disable shadowing */
1168 *cmd++ = (0 << 24) | (1 << 16) | 0;
1169#else
1170 *cmd++ = (1 << 24) | (1 << 16) | 0;
1171#endif
1172 *cmd++ = TEX_CONSTANTS;
1173
1174 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001175 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001176 *cmd++ = (2 << 16) | 0;
1177
1178 /* the next BOOL_CONSTANT dwords is the shadow area for
1179 * boolean constants.
1180 */
1181 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1182 cmd += BOOL_CONSTANTS;
1183
1184 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001185 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001186 *cmd++ = (3 << 16) | 0;
1187
1188 /* the next LOOP_CONSTANTS dwords is the shadow area for
1189 * loop constants.
1190 */
1191 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1192 cmd += LOOP_CONSTANTS;
1193
1194 /* create indirect buffer command for above command sequence */
1195 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1196
1197 tmp_ctx.cmd = cmd;
1198}
1199
Jordan Crousea78c9172011-07-11 13:14:09 -06001200static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001201build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1202 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001203{
1204 unsigned int *cmd = tmp_ctx.cmd;
1205 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001206 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001207 unsigned int *partition1;
1208 unsigned int *shaderBases, *partition2;
1209
Jordan Crousea78c9172011-07-11 13:14:09 -06001210 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1211 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001212 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1213 + _shader_shadow_size(adreno_dev);
1214 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1215 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001216
1217 /* restore shader partitioning and instructions */
1218
1219 restore = cmd; /* start address */
1220
1221 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001222 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001223 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1224
1225 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001226 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001227 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1228
1229 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001230 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001231 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1232
Jordan Crousea78c9172011-07-11 13:14:09 -06001233 /* load vertex shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001234 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001235 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1236 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1237
1238 /* load pixel shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001239 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001240 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1241 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1242
1243 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001244 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001245 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1246 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001247
1248 /* create indirect buffer command for above command sequence */
1249 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1250
1251 /*
1252 * fixup SET_SHADER_BASES data
1253 *
1254 * since self-modifying PM4 code is being used here, a seperate
1255 * command buffer is used for this fixup operation, to ensure the
1256 * commands are not read by the PM4 engine before the data fields
1257 * have been written.
1258 */
1259
1260 fixup = cmd; /* start address */
1261
1262 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001263 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001264 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1265
1266 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001267 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001268 *cmd++ = REG_SCRATCH_REG2;
1269 /* AND off invalid bits. */
1270 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001271 /* OR in instruction memory size. */
1272 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001273
1274 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001275 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001276 *cmd++ = REG_SCRATCH_REG2;
1277 /* TBD #5: shader bases (to restore) */
1278 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1279
1280 /* create indirect buffer command for above command sequence */
1281 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1282
1283 /* save shader partitioning and instructions */
1284
1285 save = cmd; /* start address */
1286
Jordan Crouse084427d2011-07-28 08:37:58 -06001287 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001288 *cmd++ = 0;
1289
1290 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1291 * store the value in the data fields of the SET_CONSTANT commands
1292 * above.
1293 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001294 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001295 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1296 /* TBD #4a: partition info (to restore) */
1297 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001298 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001299 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1300 /* TBD #4b: partition info (to fixup) */
1301 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1302
Jordan Crousea78c9172011-07-11 13:14:09 -06001303
1304 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001305 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001306 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1307 /* TBD #1: start/size (to restore) */
1308 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1309
1310 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001311 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001312 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1313 /* TBD #2: start/size (to restore) */
1314 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1315
1316 /* store the shared shader instructions if vertex base is nonzero */
1317
Jordan Crouse084427d2011-07-28 08:37:58 -06001318 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001319 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1320 /* TBD #3: start/size (to restore) */
1321 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1322
Jordan Crousea78c9172011-07-11 13:14:09 -06001323
Jordan Crouse084427d2011-07-28 08:37:58 -06001324 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001325 *cmd++ = 0;
1326
1327 /* create indirect buffer command for above command sequence */
1328 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1329
1330 tmp_ctx.cmd = cmd;
1331}
1332
1333/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001334static int a2xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001335 struct adreno_context *drawctxt)
1336{
Jordan Crousea78c9172011-07-11 13:14:09 -06001337 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1338
Jordan Crousea78c9172011-07-11 13:14:09 -06001339 /* build indirect command buffers to save & restore regs/constants */
Jordan Crousea78c9172011-07-11 13:14:09 -06001340 build_regrestore_cmds(adreno_dev, drawctxt);
1341 build_regsave_cmds(adreno_dev, drawctxt);
1342
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001343 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001344
Jordan Crousea78c9172011-07-11 13:14:09 -06001345 return 0;
1346}
1347
1348/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001349static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001350 struct adreno_context *drawctxt)
1351{
1352 int result;
1353
Anoop Kumar Yerukalaa4e88c62012-05-01 14:43:06 +05301354 calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size);
Jordan Crouse7501d452012-04-19 08:58:44 -06001355 tmp_ctx.gmem_base = adreno_dev->gmem_base;
Jordan Crousea78c9172011-07-11 13:14:09 -06001356
1357 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1358 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1359
1360 if (result)
1361 return result;
1362
Carter Cooperec549da2012-04-02 15:51:38 -06001363 /* set the gmem shadow flag for the context */
1364 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
Jordan Crousea78c9172011-07-11 13:14:09 -06001365
1366 /* blank out gmem shadow. */
1367 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1368 drawctxt->context_gmem_shadow.size);
1369
1370 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001371 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1372 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001373
1374 /* build TP0_CHICKEN register restore command buffer */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001375 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE))
1376 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001377
1378 /* build indirect command buffers to save & restore gmem */
Jordan Crousea78c9172011-07-11 13:14:09 -06001379 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1380 tmp_ctx.cmd =
1381 build_gmem2sys_cmds(adreno_dev, drawctxt,
1382 &drawctxt->context_gmem_shadow);
1383 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1384 tmp_ctx.cmd =
1385 build_sys2gmem_cmds(adreno_dev, drawctxt,
1386 &drawctxt->context_gmem_shadow);
1387
1388 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1389 KGSL_CACHE_OP_FLUSH);
1390
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001391 kgsl_cffdump_syncmem(NULL,
1392 &drawctxt->context_gmem_shadow.gmemshadow,
1393 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1394 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1395
Jordan Crousea78c9172011-07-11 13:14:09 -06001396 return 0;
1397}
1398
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001399static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
1400 struct adreno_context *drawctxt)
1401{
1402 int ret;
1403
1404 /*
1405 * Allocate memory for the GPU state and the context commands.
1406 * Despite the name, this is much more then just storage for
1407 * the gpustate. This contains command space for gmem save
1408 * and texture and vertex buffer storage too
1409 */
1410
1411 ret = kgsl_allocate(&drawctxt->gpustate,
1412 drawctxt->pagetable, _context_size(adreno_dev));
1413
1414 if (ret)
1415 return ret;
1416
1417 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1418 _context_size(adreno_dev));
1419
1420 tmp_ctx.cmd = tmp_ctx.start
1421 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1422
1423 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
1424 ret = a2xx_create_gpustate_shadow(adreno_dev, drawctxt);
1425 if (ret)
1426 goto done;
1427
1428 drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
1429 }
1430
1431 if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
1432 ret = a2xx_create_gmem_shadow(adreno_dev, drawctxt);
1433 if (ret)
1434 goto done;
1435 }
1436
1437 /* Flush and sync the gpustate memory */
1438
1439 kgsl_cache_range_op(&drawctxt->gpustate,
1440 KGSL_CACHE_OP_FLUSH);
1441
1442 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1443 drawctxt->gpustate.gpuaddr,
1444 drawctxt->gpustate.size, false);
1445
1446done:
1447 if (ret)
1448 kgsl_sharedmem_free(&drawctxt->gpustate);
1449
1450 return ret;
1451}
1452
1453static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001454 struct adreno_context *context)
1455{
1456 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001457 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001458
1459 if (context == NULL)
1460 return;
1461
1462 if (context->flags & CTXT_FLAGS_GPU_HANG)
1463 KGSL_CTXT_WARN(device,
1464 "Current active context has caused gpu hang\n");
1465
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001466 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001467
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001468 /* save registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001469 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001470 context->reg_save, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001471
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001472 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1473 /* save shader partitioning and instructions. */
1474 adreno_ringbuffer_issuecmds(device,
1475 KGSL_CMD_FLAGS_PMODE,
1476 context->shader_save, 3);
1477
1478 /*
1479 * fixup shader partitioning parameter for
1480 * SET_SHADER_BASES.
1481 */
1482 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1483 context->shader_fixup, 3);
1484
1485 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1486 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001487 }
1488
1489 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1490 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1491 /* save gmem.
1492 * (note: changes shader. shader must already be saved.)
1493 */
1494 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1495 context->context_gmem_shadow.gmem_save, 3);
1496
1497 /* Restore TP0_CHICKEN */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001498 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1499 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1500 context->chicken_restore, 3);
1501 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001502
1503 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001504 } else if (adreno_is_a225(adreno_dev)) {
1505 unsigned int *cmds = &cmd[0];
1506 /*
1507 * Issue an empty draw call to avoid possible hangs due to
1508 * repeated idles without intervening draw calls.
1509 * On adreno 225 the PC block has a cache that is only
1510 * flushed on draw calls and repeated idles can make it
1511 * overflow. The gmem save path contains draw calls so
1512 * this workaround isn't needed there.
1513 */
1514 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1515 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1516 *cmds++ = 0;
1517 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1518 *cmds++ = 0;
1519 *cmds++ = 1<<14;
1520 *cmds++ = 0;
1521 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1522 *cmds++ = 0;
1523 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1524 *cmds++ = 0x00000000;
1525
1526 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1527 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001528 }
1529}
1530
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001531static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001532 struct adreno_context *context)
1533{
1534 struct kgsl_device *device = &adreno_dev->dev;
1535 unsigned int cmds[5];
1536
1537 if (context == NULL) {
1538 /* No context - set the default apgetable and thats it */
Shubhraprakash Das79447952012-04-26 18:12:23 -06001539 kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
Jordan Crousea78c9172011-07-11 13:14:09 -06001540 return;
1541 }
1542
1543 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1544
Jordan Crouse084427d2011-07-28 08:37:58 -06001545 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001546 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001547 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001548 cmds[3] = device->memstore.gpuaddr +
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001549 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
1550 cmds[4] = context->id;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001551 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
Shubhraprakash Das79447952012-04-26 18:12:23 -06001552 kgsl_mmu_setstate(&device->mmu, context->pagetable);
Jordan Crousea78c9172011-07-11 13:14:09 -06001553
1554#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1555 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1556 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1557 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1558#endif
1559
1560 /* restore gmem.
1561 * (note: changes shader. shader must not already be restored.)
1562 */
1563 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1564 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1565 context->context_gmem_shadow.gmem_restore, 3);
1566
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001567 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1568 /* Restore TP0_CHICKEN */
1569 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1570 context->chicken_restore, 3);
1571 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001572
1573 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1574 }
1575
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001576 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001577
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001578 /* restore registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001579 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001580 context->reg_restore, 3);
1581
1582 /* restore shader instructions & partitioning. */
1583 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1584 adreno_ringbuffer_issuecmds(device,
1585 KGSL_CMD_FLAGS_NONE,
1586 context->shader_restore, 3);
1587 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001588 }
1589
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001590 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001591 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001592 cmds[1] = context->bin_base_offset;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001593 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1594 cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001595 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001596}
1597
1598/*
1599 * Interrupt management
1600 *
1601 * a2xx interrupt control is distributed among the various
1602 * hardware components (RB, CP, MMU). The main interrupt
1603 * tells us which component fired the interrupt, but one needs
1604 * to go to the individual component to find out why. The
1605 * following functions provide the broken out support for
1606 * managing the interrupts
1607 */
1608
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001609#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001610
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001611#define CP_INT_MASK \
1612 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001613 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1614 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1615 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1616 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001617 CP_INT_CNTL__IB1_INT_MASK | \
1618 CP_INT_CNTL__RB_INT_MASK)
1619
1620#define VALID_STATUS_COUNT_MAX 10
1621
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001622static struct {
1623 unsigned int mask;
1624 const char *message;
1625} kgsl_cp_error_irqs[] = {
1626 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1627 "ringbuffer TO packet in IB interrupt" },
1628 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1629 "ringbuffer opcode error interrupt" },
1630 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1631 "ringbuffer protected mode error interrupt" },
1632 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1633 "ringbuffer reserved bit error interrupt" },
1634 { CP_INT_CNTL__IB_ERROR_MASK,
1635 "ringbuffer IB error interrupt" },
1636};
1637
Jordan Crousea78c9172011-07-11 13:14:09 -06001638static void a2xx_cp_intrcallback(struct kgsl_device *device)
1639{
1640 unsigned int status = 0, num_reads = 0, master_status = 0;
1641 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1642 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001643 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001644
1645 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1646 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1647 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1648 adreno_regread(device, REG_CP_INT_STATUS, &status);
1649 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1650 &master_status);
1651 num_reads++;
1652 }
1653 if (num_reads > 1)
1654 KGSL_DRV_WARN(device,
1655 "Looped %d times to read REG_CP_INT_STATUS\n",
1656 num_reads);
Norman Geed7402ff2011-10-28 08:51:11 -06001657
1658 trace_kgsl_a2xx_irq_status(device, master_status, status);
1659
Jordan Crousea78c9172011-07-11 13:14:09 -06001660 if (!status) {
1661 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1662 /* This indicates that we could not read CP_INT_STAT.
1663 * As a precaution just wake up processes so
1664 * they can check their timestamps. Since, we
1665 * did not ack any interrupts this interrupt will
1666 * be generated again */
1667 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1668 wake_up_interruptible_all(&device->wait_queue);
1669 } else
1670 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1671 return;
1672 }
1673
1674 if (status & CP_INT_CNTL__RB_INT_MASK) {
1675 /* signal intr completion event */
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001676 unsigned int context_id;
1677 kgsl_sharedmem_readl(&device->memstore,
1678 &context_id,
1679 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
1680 current_context));
1681 if (context_id < KGSL_MEMSTORE_MAX) {
1682 kgsl_sharedmem_writel(&rb->device->memstore,
1683 KGSL_MEMSTORE_OFFSET(context_id,
1684 ts_cmp_enable), 0);
1685 device->last_expired_ctxt_id = context_id;
1686 wmb();
1687 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001688 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1689 }
1690
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001691 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1692 if (status & kgsl_cp_error_irqs[i].mask) {
1693 KGSL_CMD_CRIT(rb->device, "%s\n",
1694 kgsl_cp_error_irqs[i].message);
1695 /*
1696 * on fatal errors, turn off the interrupts to
1697 * avoid storming. This has the side effect of
1698 * forcing a PM dump when the timestamp times out
1699 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001700
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001701 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1702 }
1703 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001704
1705 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001706 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001707 adreno_regwrite(device, REG_CP_INT_ACK, status);
1708
1709 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1710 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001711 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001712 wake_up_interruptible_all(&device->wait_queue);
1713 atomic_notifier_call_chain(&(device->ts_notifier_list),
1714 device->id,
1715 NULL);
1716 }
1717}
1718
1719static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1720{
1721 unsigned int status = 0;
1722 unsigned int rderr = 0;
Jeremy Gebben22784c22012-03-07 16:02:08 -07001723 unsigned int addr = 0;
1724 const char *source;
Jordan Crousea78c9172011-07-11 13:14:09 -06001725
1726 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1727
1728 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001729 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
Jeremy Gebben22784c22012-03-07 16:02:08 -07001730 source = (rderr & RBBM_READ_ERROR_REQUESTER)
1731 ? "host" : "cp";
1732 /* convert to dword address */
1733 addr = (rderr & RBBM_READ_ERROR_ADDRESS_MASK) >> 2;
1734
1735 /*
1736 * Log CP_INT_STATUS interrupts from the CP at a
1737 * lower level because they can happen frequently
1738 * and are worked around in a2xx_irq_handler.
1739 */
1740 if (addr == REG_CP_INT_STATUS &&
1741 rderr & RBBM_READ_ERROR_ERROR &&
1742 rderr & RBBM_READ_ERROR_REQUESTER)
Jordan Crousea78c9172011-07-11 13:14:09 -06001743 KGSL_DRV_WARN(device,
Jeremy Gebben22784c22012-03-07 16:02:08 -07001744 "rbbm read error interrupt: %s reg: %04X\n",
1745 source, addr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001746 else
1747 KGSL_DRV_CRIT(device,
Jeremy Gebben22784c22012-03-07 16:02:08 -07001748 "rbbm read error interrupt: %s reg: %04X\n",
1749 source, addr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001750 }
1751
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001752 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001753 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1754}
1755
1756irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1757{
1758 struct kgsl_device *device = &adreno_dev->dev;
1759 irqreturn_t result = IRQ_NONE;
1760 unsigned int status;
1761
1762 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1763
1764 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1765 kgsl_mh_intrcallback(device);
1766 result = IRQ_HANDLED;
1767 }
1768
1769 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1770 a2xx_cp_intrcallback(device);
1771 result = IRQ_HANDLED;
1772 }
1773
1774 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1775 a2xx_rbbm_intrcallback(device);
1776 result = IRQ_HANDLED;
1777 }
1778
1779 return result;
1780}
1781
1782static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1783{
1784 struct kgsl_device *device = &adreno_dev->dev;
1785
1786 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001787 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1788 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001789 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1790 } else {
1791 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1792 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1793 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1794 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001795
1796 /* Force the writes to post before touching the IRQ line */
1797 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001798}
1799
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001800static void a2xx_rb_init(struct adreno_device *adreno_dev,
1801 struct adreno_ringbuffer *rb)
1802{
1803 unsigned int *cmds, cmds_gpu;
1804
1805 /* ME_INIT */
1806 cmds = adreno_ringbuffer_allocspace(rb, 19);
1807 cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
1808
1809 GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
1810 /* All fields present (bits 9:0) */
1811 GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff);
1812 /* Disable/Enable Real-Time Stream processing (present but ignored) */
1813 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1814 /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
1815 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1816
1817 GSL_RB_WRITE(cmds, cmds_gpu,
1818 SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO));
1819 GSL_RB_WRITE(cmds, cmds_gpu,
1820 SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET));
1821 GSL_RB_WRITE(cmds, cmds_gpu,
1822 SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX));
1823 GSL_RB_WRITE(cmds, cmds_gpu,
1824 SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL));
1825 GSL_RB_WRITE(cmds, cmds_gpu,
1826 SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL));
1827 GSL_RB_WRITE(cmds, cmds_gpu,
1828 SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE));
1829 GSL_RB_WRITE(cmds, cmds_gpu,
1830 SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL));
1831 GSL_RB_WRITE(cmds, cmds_gpu,
1832 SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
1833
1834 /* Instruction memory size: */
1835 GSL_RB_WRITE(cmds, cmds_gpu,
1836 (adreno_encode_istore_size(adreno_dev)
1837 | adreno_dev->pix_shader_start));
1838 /* Maximum Contexts */
1839 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
1840 /* Write Confirm Interval and The CP will wait the
1841 * wait_interval * 16 clocks between polling */
1842 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1843
1844 /* NQ and External Memory Swap */
1845 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
Shubhraprakash Dasc6e21012012-05-11 17:24:51 -06001846 /* Protected mode error checking
1847 * If iommu is used then protection needs to be turned off
1848 * to enable context bank switching */
1849 if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
1850 GSL_RB_WRITE(cmds, cmds_gpu, 0);
1851 else
1852 GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001853 /* Disable header dumping and Header dump address */
1854 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1855 /* Header dump size */
1856 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1857
1858 adreno_ringbuffer_submit(rb);
1859}
1860
1861static unsigned int a2xx_busy_cycles(struct adreno_device *adreno_dev)
1862{
1863 struct kgsl_device *device = &adreno_dev->dev;
1864 unsigned int reg, val;
1865
1866 /* Freeze the counter */
1867 adreno_regwrite(device, REG_CP_PERFMON_CNTL,
1868 REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE);
1869
1870 /* Get the value */
1871 adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
1872
1873 /* Reset the counter */
1874 adreno_regwrite(device, REG_CP_PERFMON_CNTL,
1875 REG_PERF_MODE_CNT | REG_PERF_STATE_RESET);
1876
1877 /* Re-Enable the performance monitors */
1878 adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
1879 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
1880 adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
1881 adreno_regwrite(device, REG_CP_PERFMON_CNTL,
1882 REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE);
1883
1884 return val;
1885}
1886
1887static void a2xx_gmeminit(struct adreno_device *adreno_dev)
1888{
1889 struct kgsl_device *device = &adreno_dev->dev;
1890 union reg_rb_edram_info rb_edram_info;
1891 unsigned int gmem_size;
1892 unsigned int edram_value = 0;
1893
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001894 /* get edram_size value equivalent */
Jordan Crouse7501d452012-04-19 08:58:44 -06001895 gmem_size = (adreno_dev->gmem_size >> 14);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001896 while (gmem_size >>= 1)
1897 edram_value++;
1898
1899 rb_edram_info.val = 0;
1900
1901 rb_edram_info.f.edram_size = edram_value;
1902 rb_edram_info.f.edram_mapping_mode = 0; /* EDRAM_MAP_UPPER */
1903
1904 /* must be aligned to size */
Jordan Crouse7501d452012-04-19 08:58:44 -06001905 rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001906
1907 adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
1908}
1909
1910static void a2xx_start(struct adreno_device *adreno_dev)
1911{
1912 struct kgsl_device *device = &adreno_dev->dev;
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001913
1914 /*
1915 * We need to make sure all blocks are powered up and clocked
1916 * before issuing a soft reset. The overrides will then be
1917 * turned off (set to 0)
1918 */
1919 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
1920 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
1921
1922 /*
1923 * Only reset CP block if all blocks have previously been
1924 * reset
1925 */
1926 if (!(device->flags & KGSL_FLAGS_SOFT_RESET) ||
1927 !adreno_is_a22x(adreno_dev)) {
1928 adreno_regwrite(device, REG_RBBM_SOFT_RESET,
1929 0xFFFFFFFF);
1930 device->flags |= KGSL_FLAGS_SOFT_RESET;
1931 } else {
1932 adreno_regwrite(device, REG_RBBM_SOFT_RESET,
1933 0x00000001);
1934 }
1935 /*
1936 * The core is in an indeterminate state until the reset
1937 * completes after 30ms.
1938 */
1939 msleep(30);
1940
1941 adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
1942
1943 if (adreno_is_a225(adreno_dev)) {
1944 /* Enable large instruction store for A225 */
1945 adreno_regwrite(device, REG_SQ_FLOW_CONTROL,
1946 0x18000000);
1947 }
1948
1949 adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
1950
1951 adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
1952 adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
1953
Sudhakara Rao Tentudaebac22012-04-02 14:51:29 -07001954 if (cpu_is_msm8960())
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001955 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
1956 else
1957 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
1958
1959 if (!adreno_is_a22x(adreno_dev))
1960 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
1961 else
1962 adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
1963
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001964 adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
1965
1966 /* Make sure interrupts are disabled */
1967 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1968 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1969 adreno_regwrite(device, REG_SQ_INT_CNTL, 0);
1970
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001971 a2xx_gmeminit(adreno_dev);
1972}
1973
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001974/* Defined in adreno_a2xx_snapshot.c */
1975void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
1976 int *remain, int hang);
1977
Jordan Crousea78c9172011-07-11 13:14:09 -06001978struct adreno_gpudev adreno_a2xx_gpudev = {
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001979 .reg_rbbm_status = REG_RBBM_STATUS,
1980 .reg_cp_pfp_ucode_addr = REG_CP_PFP_UCODE_ADDR,
1981 .reg_cp_pfp_ucode_data = REG_CP_PFP_UCODE_DATA,
1982
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001983 .ctxt_create = a2xx_drawctxt_create,
1984 .ctxt_save = a2xx_drawctxt_save,
1985 .ctxt_restore = a2xx_drawctxt_restore,
Jordan Crousea78c9172011-07-11 13:14:09 -06001986 .irq_handler = a2xx_irq_handler,
1987 .irq_control = a2xx_irq_control,
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001988 .snapshot = a2xx_snapshot,
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001989 .rb_init = a2xx_rb_init,
1990 .busy_cycles = a2xx_busy_cycles,
1991 .start = a2xx_start,
Jordan Crousea78c9172011-07-11 13:14:09 -06001992};