blob: eb936f8fced504afb4c1ffbbdf6a5ef3d07063f6 [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>
15#include <mach/socinfo.h>
16
Jordan Crousea78c9172011-07-11 13:14:09 -060017#include "kgsl.h"
18#include "kgsl_sharedmem.h"
19#include "kgsl_cffdump.h"
20#include "adreno.h"
Norman Geed7402ff2011-10-28 08:51:11 -060021#include "adreno_a2xx_trace.h"
Jordan Crousea78c9172011-07-11 13:14:09 -060022
23/*
Jordan Crousef7597bf2012-01-03 08:43:34 -070024 * These are the registers that are dumped with GPU snapshot
25 * and postmortem. The lists are dword offset pairs in the
26 * form of {start offset, end offset} inclusive.
27 */
28
29/* A200, A205 */
30const unsigned int a200_registers[] = {
31 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
32 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
33 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
34 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
35 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
36 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
37 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
38 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
39 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
40 0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
41 0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
42 0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
43 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
44 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
45 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
46 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
47 0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
48 0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
49 0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
50 0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
51 0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
52 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
53 0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
54 0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
55 0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
56};
57
Jordan Crousef7597bf2012-01-03 08:43:34 -070058const unsigned int a220_registers[] = {
59 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
60 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
61 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
62 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
63 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
64 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
65 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
66 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
67 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
68 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
69 0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
70 0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
71 0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
72 0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
73 0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
74 0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
75 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
76 0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
77 0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
78 0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
79 0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
80 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
81 0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
82 0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
83 0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
84 0x4900, 0x4900, 0x4908, 0x4908,
85};
86
Jeremy Gebben6be78d12012-03-07 16:02:47 -070087const unsigned int a225_registers[] = {
88 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
89 0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1,
90 0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA,
91 0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392,
92 0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB,
93 0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F,
94 0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587,
95 0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609,
96 0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31,
97 0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F,
98 0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C,
99 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06,
100 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
101 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
102 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
103 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082,
104 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7,
105 0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222,
106 0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A,
107 0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326,
108 0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F,
109 0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584,
110 0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610,
111 0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697,
112 0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D,
113 0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783,
114 0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900,
115 0x4908, 0x4908,
116};
117
Jordan Crousef7597bf2012-01-03 08:43:34 -0700118const unsigned int a200_registers_count = ARRAY_SIZE(a200_registers) / 2;
119const unsigned int a220_registers_count = ARRAY_SIZE(a220_registers) / 2;
Jeremy Gebben6be78d12012-03-07 16:02:47 -0700120const unsigned int a225_registers_count = ARRAY_SIZE(a225_registers) / 2;
Jordan Crousef7597bf2012-01-03 08:43:34 -0700121
122/*
Jordan Crousea78c9172011-07-11 13:14:09 -0600123 *
124 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
125 * (34.5KB)
126 *
127 * +---------------------+------------+-------------+---+---------------------+
128 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
129 * +---------------------+------------+-------------+---+---------------------+
130 * ________________________________/ \____________________
131 * / |
132 * +--------------+-----------+------+-----------+------------------------+
133 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
134 * +--------------+-----------+------+-----------+------------------------+
135 *
136 * 8K - ALU Constant Shadow (8K aligned)
137 * 4K - H/W Register Shadow (8K aligned)
138 * 4K - Command and Vertex Buffers
139 * - Indirect command buffer : Const/Reg restore
140 * - includes Loop & Bool const shadows
141 * - Indirect command buffer : Const/Reg save
142 * - Quad vertices & texture coordinates
143 * - Indirect command buffer : Gmem save
144 * - Indirect command buffer : Gmem restore
145 * - Unused (padding to 8KB boundary)
146 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
147 * 18K - Shader Instruction Shadow
148 * - 6K vertex (32 byte aligned)
149 * - 6K pixel (32 byte aligned)
150 * - 6K shared (32 byte aligned)
151 *
152 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
153 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
154 * 16 bytes per constant. If the texture constants were transfered this way,
155 * the Command & Vertex Buffers section would extend past the 16K boundary.
156 * By moving the texture constant shadow area to start at 16KB boundary, we
157 * only require approximately 40 bytes more memory, but are able to use the
158 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
159 * context switching.
160 *
161 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
162 * constants would require an additional 8KB each, for alignment.]
163 *
164 */
165
166/* Constants */
167
168#define ALU_CONSTANTS 2048 /* DWORDS */
169#define NUM_REGISTERS 1024 /* DWORDS */
170#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
171#define CMD_BUFFER_LEN 9216 /* DWORDS */
172#else
173#define CMD_BUFFER_LEN 3072 /* DWORDS */
174#endif
175#define TEX_CONSTANTS (32*6) /* DWORDS */
176#define BOOL_CONSTANTS 8 /* DWORDS */
177#define LOOP_CONSTANTS 56 /* DWORDS */
Jordan Crousea78c9172011-07-11 13:14:09 -0600178
179/* LOAD_CONSTANT_CONTEXT shadow size */
180#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
181
182#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
183#define REG_SHADOW_SIZE 0x1000 /* 4KB */
184#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
185#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
186#else
187#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
188#endif
189#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
Jordan Crousea78c9172011-07-11 13:14:09 -0600190
191#define REG_OFFSET LCC_SHADOW_SIZE
192#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
193#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
194#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
195
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700196static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
197{
Jordan Crousec6b3a992012-02-04 10:23:51 -0700198 return adreno_dev->istore_size *
199 (adreno_dev->instruction_size * sizeof(unsigned int));
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700200}
201
202static inline int _context_size(struct adreno_device *adreno_dev)
203{
204 return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
205}
Jordan Crousea78c9172011-07-11 13:14:09 -0600206
207/* A scratchpad used to build commands during context create */
208
209static struct tmp_ctx {
210 unsigned int *start; /* Command & Vertex buffer start */
211 unsigned int *cmd; /* Next available dword in C&V buffer */
212
213 /* address of buffers, needed when creating IB1 command buffers. */
214 uint32_t bool_shadow; /* bool constants */
215 uint32_t loop_shadow; /* loop constants */
216
Jordan Crousea78c9172011-07-11 13:14:09 -0600217 uint32_t shader_shared; /* shared shader instruction shadow */
218 uint32_t shader_vertex; /* vertex shader instruction shadow */
219 uint32_t shader_pixel; /* pixel shader instruction shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -0600220
221 /* Addresses in command buffer where separately handled registers
222 * are saved
223 */
224 uint32_t reg_values[33];
225 uint32_t chicken_restore;
226
227 uint32_t gmem_base; /* Base gpu address of GMEM */
228
229} tmp_ctx;
230
231/* context save (gmem -> sys) */
232
233/* pre-compiled vertex shader program
234*
235* attribute vec4 P;
236* void main(void)
237* {
238* gl_Position = P;
239* }
240*/
241#define GMEM2SYS_VTX_PGM_LEN 0x12
242
243static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
244 0x00011003, 0x00001000, 0xc2000000,
245 0x00001004, 0x00001000, 0xc4000000,
246 0x00001005, 0x00002000, 0x00000000,
247 0x1cb81000, 0x00398a88, 0x00000003,
248 0x140f803e, 0x00000000, 0xe2010100,
249 0x14000000, 0x00000000, 0xe2000000
250};
251
252/* pre-compiled fragment shader program
253*
254* precision highp float;
255* uniform vec4 clear_color;
256* void main(void)
257* {
258* gl_FragColor = clear_color;
259* }
260*/
261
262#define GMEM2SYS_FRAG_PGM_LEN 0x0c
263
264static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
265 0x00000000, 0x1002c400, 0x10000000,
266 0x00001003, 0x00002000, 0x00000000,
267 0x140f8000, 0x00000000, 0x22000000,
268 0x14000000, 0x00000000, 0xe2000000
269};
270
271/* context restore (sys -> gmem) */
272/* pre-compiled vertex shader program
273*
274* attribute vec4 position;
275* attribute vec4 texcoord;
276* varying vec4 texcoord0;
277* void main()
278* {
279* gl_Position = position;
280* texcoord0 = texcoord;
281* }
282*/
283
284#define SYS2GMEM_VTX_PGM_LEN 0x18
285
286static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
287 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
288 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
289 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
290 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
291 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
292 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
293};
294
295/* pre-compiled fragment shader program
296*
297* precision mediump float;
298* uniform sampler2D tex0;
299* varying vec4 texcoord0;
300* void main()
301* {
302* gl_FragColor = texture2D(tex0, texcoord0.xy);
303* }
304*/
305
306#define SYS2GMEM_FRAG_PGM_LEN 0x0f
307
308static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
309 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
310 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
311 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
312 0x14000000, 0x00000000, 0xe2000000
313};
314
315/* shader texture constants (sysmem -> gmem) */
316#define SYS2GMEM_TEX_CONST_LEN 6
317
318static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
319 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
320 * RFMode=ZeroClamp-1, Dim=1:2d
321 */
322 0x00000002, /* Pitch = TBD */
323
324 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
325 * NearestClamp=1:OGL Mode
326 */
327 0x00000800, /* Address[31:12] = TBD */
328
329 /* Width, Height, EndianSwap=0:None */
330 0, /* Width & Height = TBD */
331
332 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
333 * Mip=2:BaseMap
334 */
335 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
336
337 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
338 * Dim3d=0
339 */
340 0,
341
342 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
343 * Dim=1:2d, MipPacking=0
344 */
345 1 << 9 /* Mip Address[31:12] = TBD */
346};
347
Jordan Crousea78c9172011-07-11 13:14:09 -0600348#define NUM_COLOR_FORMATS 13
349
350static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
351 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
352 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
353 FMT_5_6_5, /* COLORX_5_6_5 */
354 FMT_8, /* COLORX_8 */
355 FMT_8_8, /* COLORX_8_8 */
356 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
357 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
358 FMT_16_FLOAT, /* COLORX_16_FLOAT */
359 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
360 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
361 FMT_32_FLOAT, /* COLORX_32_FLOAT */
362 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
363 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
364};
365
366static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
367 2, /* COLORX_4_4_4_4 */
368 2, /* COLORX_1_5_5_5 */
369 2, /* COLORX_5_6_5 */
370 1, /* COLORX_8 */
371 2, /* COLORX_8_8 8*/
372 4, /* COLORX_8_8_8_8 */
373 4, /* COLORX_S8_8_8_8 */
374 2, /* COLORX_16_FLOAT */
375 4, /* COLORX_16_16_FLOAT */
376 8, /* COLORX_16_16_16_16_FLOAT */
377 4, /* COLORX_32_FLOAT */
378 8, /* COLORX_32_32_FLOAT */
379 16, /* COLORX_32_32_32_32_FLOAT */
380};
381
382/* shader linkage info */
383#define SHADER_CONST_ADDR (11 * 6 + 3)
384
Jordan Crousea78c9172011-07-11 13:14:09 -0600385
386static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
387 unsigned int *shader_pgm, int dwords)
388{
389 /* load the patched vertex shader stream */
Jordan Crouse084427d2011-07-28 08:37:58 -0600390 *cmds++ = cp_type3_packet(CP_IM_LOAD_IMMEDIATE, 2 + dwords);
Jordan Crousea78c9172011-07-11 13:14:09 -0600391 /* 0=vertex shader, 1=fragment shader */
392 *cmds++ = vtxfrag;
393 /* instruction start & size (in 32-bit words) */
394 *cmds++ = ((0 << 16) | dwords);
395
396 memcpy(cmds, shader_pgm, dwords << 2);
397 cmds += dwords;
398
399 return cmds;
400}
401
402static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
403 uint32_t src, int dwords)
404{
405 while (dwords-- > 0) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600406 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600407 *cmds++ = src++;
408 *cmds++ = dst;
409 dst += 4;
410 }
411
412 return cmds;
413}
414
415#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
416
417static void build_reg_to_mem_range(unsigned int start, unsigned int end,
418 unsigned int **cmd,
419 struct adreno_context *drawctxt)
420{
421 unsigned int i = start;
422
423 for (i = start; i <= end; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600424 *(*cmd)++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600425 *(*cmd)++ = i;
426 *(*cmd)++ =
427 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
428 (i - 0x2000) * 4;
429 }
430}
431
432#endif
433
434/* chicken restore */
435static unsigned int *build_chicken_restore_cmds(
436 struct adreno_context *drawctxt)
437{
438 unsigned int *start = tmp_ctx.cmd;
439 unsigned int *cmds = start;
440
Jordan Crouse084427d2011-07-28 08:37:58 -0600441 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600442 *cmds++ = 0;
443
Jordan Crouse084427d2011-07-28 08:37:58 -0600444 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600445 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
446 *cmds++ = 0x00000000;
447
448 /* create indirect buffer command for above command sequence */
449 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
450
451 return cmds;
452}
453
454/****************************************************************************/
455/* context save */
456/****************************************************************************/
457
458static const unsigned int register_ranges_a20x[] = {
459 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
460 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
461 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
462 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
463 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
464 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
465 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
466 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
467 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
468 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
469 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
470 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
471 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
472 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
473};
474
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700475static const unsigned int register_ranges_a220[] = {
Jordan Crousea78c9172011-07-11 13:14:09 -0600476 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
477 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
478 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
479 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
480 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
481 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
482 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
483 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
484 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700485 REG_A220_PC_MAX_VTX_INDX, REG_A220_PC_INDX_OFFSET,
Jordan Crousea78c9172011-07-11 13:14:09 -0600486 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
487 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
488 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
489 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
490 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700491 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
492 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
Jordan Crousea78c9172011-07-11 13:14:09 -0600493 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
494};
495
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700496static const unsigned int register_ranges_a225[] = {
497 REG_RB_SURFACE_INFO, REG_A225_RB_COLOR_INFO3,
498 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
499 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
500 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
501 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
502 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
503 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
504 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
505 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
506 REG_A220_PC_MAX_VTX_INDX, REG_A225_PC_MULTI_PRIM_IB_RESET_INDX,
507 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
508 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
509 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
510 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
511 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
512 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
513 REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
514 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
Jeremy Gebbene139a042011-11-17 16:20:41 -0700515 REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
516 REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700517};
518
Jordan Crousea78c9172011-07-11 13:14:09 -0600519
520/* save h/w regs, alu constants, texture contants, etc. ...
521* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
522*/
523static void build_regsave_cmds(struct adreno_device *adreno_dev,
524 struct adreno_context *drawctxt)
525{
526 unsigned int *start = tmp_ctx.cmd;
527 unsigned int *cmd = start;
528
Jordan Crouse084427d2011-07-28 08:37:58 -0600529 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600530 *cmd++ = 0;
531
532#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
533 /* Make sure the HW context has the correct register values
534 * before reading them. */
Jordan Crouse084427d2011-07-28 08:37:58 -0600535 *cmd++ = cp_type3_packet(CP_CONTEXT_UPDATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600536 *cmd++ = 0;
537
538 {
539 unsigned int i = 0;
540 unsigned int reg_array_size = 0;
541 const unsigned int *ptr_register_ranges;
542
543 /* Based on chip id choose the register ranges */
Jeremy Gebben99105cb2011-08-31 10:23:05 -0700544 if (adreno_is_a220(adreno_dev)) {
545 ptr_register_ranges = register_ranges_a220;
546 reg_array_size = ARRAY_SIZE(register_ranges_a220);
547 } else if (adreno_is_a225(adreno_dev)) {
548 ptr_register_ranges = register_ranges_a225;
549 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -0600550 } else {
551 ptr_register_ranges = register_ranges_a20x;
552 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
553 }
554
555
556 /* Write HW registers into shadow */
557 for (i = 0; i < (reg_array_size/2) ; i++) {
558 build_reg_to_mem_range(ptr_register_ranges[i*2],
559 ptr_register_ranges[i*2+1],
560 &cmd, drawctxt);
561 }
562 }
563
564 /* Copy ALU constants */
565 cmd =
566 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
567 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
568
569 /* Copy Tex constants */
570 cmd =
571 reg_to_mem(cmd,
572 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
573 REG_SQ_FETCH_0, TEX_CONSTANTS);
574#else
575
576 /* Insert a wait for idle packet before reading the registers.
577 * This is to fix a hang/reset seen during stress testing. In this
578 * hang, CP encountered a timeout reading SQ's boolean constant
579 * register. There is logic in the HW that blocks reading of this
580 * register when the SQ block is not idle, which we believe is
581 * contributing to the hang.*/
Jordan Crouse084427d2011-07-28 08:37:58 -0600582 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600583 *cmd++ = 0;
584
585 /* H/w registers are already shadowed; just need to disable shadowing
586 * to prevent corruption.
587 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600588 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600589 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
590 *cmd++ = 4 << 16; /* regs, start=0 */
591 *cmd++ = 0x0; /* count = 0 */
592
593 /* ALU constants are already shadowed; just need to disable shadowing
594 * to prevent corruption.
595 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600596 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600597 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
598 *cmd++ = 0 << 16; /* ALU, start=0 */
599 *cmd++ = 0x0; /* count = 0 */
600
601 /* Tex constants are already shadowed; just need to disable shadowing
602 * to prevent corruption.
603 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600604 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600605 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
606 *cmd++ = 1 << 16; /* Tex, start=0 */
607 *cmd++ = 0x0; /* count = 0 */
608#endif
609
610 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -0600611 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600612 *cmd++ = REG_SQ_GPR_MANAGEMENT;
613 *cmd++ = tmp_ctx.reg_values[0];
614
Jordan Crouse084427d2011-07-28 08:37:58 -0600615 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600616 *cmd++ = REG_TP0_CHICKEN;
617 *cmd++ = tmp_ctx.reg_values[1];
618
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600619 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600620 unsigned int i;
621 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700622 for (i = REG_A220_VSC_BIN_SIZE; i <=
623 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600624 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600625 *cmd++ = i;
626 *cmd++ = tmp_ctx.reg_values[j];
627 j++;
628 }
629 }
630
631 /* Copy Boolean constants */
632 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
633 BOOL_CONSTANTS);
634
635 /* Copy Loop constants */
636 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
637 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
638
639 /* create indirect buffer command for above command sequence */
640 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
641
642 tmp_ctx.cmd = cmd;
643}
644
645/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
646static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
647 struct adreno_context *drawctxt,
648 struct gmem_shadow_t *shadow)
649{
650 unsigned int *cmds = shadow->gmem_save_commands;
651 unsigned int *start = cmds;
652 /* Calculate the new offset based on the adjusted base */
653 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
654 unsigned int addr = shadow->gmemshadow.gpuaddr;
655 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
656
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700657 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
658 /* Store TP0_CHICKEN register */
659 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
660 *cmds++ = REG_TP0_CHICKEN;
Jordan Crousea78c9172011-07-11 13:14:09 -0600661
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700662 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600663
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700664 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
665 *cmds++ = 0;
666 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600667
668 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600669 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600670 *cmds++ = 0x00000000;
671
672 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600673 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600674 *cmds++ = 0x00000000;
675
676 /* program shader */
677
678 /* load shader vtx constants ... 5 dwords */
Jordan Crouse084427d2011-07-28 08:37:58 -0600679 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crousea78c9172011-07-11 13:14:09 -0600680 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
681 *cmds++ = 0;
682 /* valid(?) vtx constant flag & addr */
683 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
684 /* limit = 12 dwords */
685 *cmds++ = 0x00000030;
686
687 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600688 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600689 *cmds++ = 0x1;
690
Jordan Crouse084427d2011-07-28 08:37:58 -0600691 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600692 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600693 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
694 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
695 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
696
Jordan Crouse084427d2011-07-28 08:37:58 -0600697 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600698 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600699 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
700
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_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600703 *cmds++ = 0x00000c20;
704
Tarun Karra16346b02011-07-24 15:04:26 -0700705 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600706 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700707 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700708
709 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600710 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700711 *cmds++ = 0x00003F00;
712
Jordan Crouse084427d2011-07-28 08:37:58 -0600713 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700714 *cmds++ = adreno_encode_istore_size(adreno_dev)
715 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700716
Jordan Crousea78c9172011-07-11 13:14:09 -0600717 /* load the patched vertex shader stream */
718 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
719
720 /* Load the patched fragment shader stream */
721 cmds =
722 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
723
724 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600725 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600726 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600727 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600728 *cmds++ = 0x10018001;
729 else
730 *cmds++ = 0x10010001;
731 *cmds++ = 0x00000008;
732
733 /* resolve */
734
735 /* PA_CL_VTE_CNTL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600736 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600737 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600738 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
739 *cmds++ = 0x00000b00;
740
741 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600742 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600743 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600744 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
745
746 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
747 * Base=gmem_base
748 */
749 /* gmem base assumed 4K aligned. */
750 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
751 *cmds++ =
752 (shadow->
753 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
754
755 /* disable Z */
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_DEPTHCONTROL);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600758 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -0600759 *cmds++ = 0x08;
760 else
761 *cmds++ = 0;
762
763 /* set REG_PA_SU_SC_MODE_CNTL
764 * Front_ptype = draw triangles
765 * Back_ptype = draw triangles
766 * Provoking vertex = last
767 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600768 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600769 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600770 *cmds++ = 0x00080240;
771
772 /* Use maximum scissor values -- quad vertices already have the
773 * correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -0600774 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600775 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600776 *cmds++ = (0 << 16) | 0;
777 *cmds++ = (0x1fff << 16) | (0x1fff);
Jordan Crouse084427d2011-07-28 08:37:58 -0600778 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600779 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600780 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
781 *cmds++ = (0x1fff << 16) | (0x1fff);
782
783 /* load the viewport so that z scale = clear depth and
784 * z offset = 0.0f
785 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600786 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600787 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -0600788 *cmds++ = 0xbf800000; /* -1.0f */
789 *cmds++ = 0x0;
790
Jordan Crouse084427d2011-07-28 08:37:58 -0600791 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600792 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600793 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
794
Jordan Crouse084427d2011-07-28 08:37:58 -0600795 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600796 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600797 *cmds++ = 0xffffffff;
798
Jordan Crouse084427d2011-07-28 08:37:58 -0600799 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600800 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -0600801 *cmds++ = 0x00000000;
802 *cmds++ = 0x00000000;
803
804 /* load the stencil ref value
805 * $AAM - do this later
806 */
807
808 /* load the COPY state */
Jordan Crouse084427d2011-07-28 08:37:58 -0600809 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 6);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600810 *cmds++ = CP_REG(REG_RB_COPY_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600811 *cmds++ = 0; /* RB_COPY_CONTROL */
812 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
813 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
814
815 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
816 * MaskWrite:R=G=B=A=1
817 */
818 *cmds++ = 0x0003c008 |
819 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
820 /* Make sure we stay in offsetx field. */
821 BUG_ON(offset & 0xfffff000);
822 *cmds++ = offset;
823
Jordan Crouse084427d2011-07-28 08:37:58 -0600824 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600825 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600826 *cmds++ = 0x6; /* EDRAM copy */
827
Jordan Crouse084427d2011-07-28 08:37:58 -0600828 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600829 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600830 *cmds++ = 0x00010000;
831
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600832 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -0600833 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600834 *cmds++ = 0;
835
Jordan Crouse084427d2011-07-28 08:37:58 -0600836 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -0700837 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600838 *cmds++ = 0x0000000;
839
Jordan Crouse084427d2011-07-28 08:37:58 -0600840 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -0600841 *cmds++ = 0; /* viz query info. */
842 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
843 *cmds++ = 0x00004088;
844 *cmds++ = 3; /* NumIndices=3 */
845 } else {
846 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -0600847 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -0600848 *cmds++ = 0; /* viz query info. */
849 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
850 *cmds++ = 0x00030088;
851 }
852
853 /* create indirect buffer command for above command sequence */
854 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
855
856 return cmds;
857}
858
859/* context restore */
860
861/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
862static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
863 struct adreno_context *drawctxt,
864 struct gmem_shadow_t *shadow)
865{
866 unsigned int *cmds = shadow->gmem_restore_commands;
867 unsigned int *start = cmds;
868
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700869 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
870 /* Store TP0_CHICKEN register */
871 *cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
872 *cmds++ = REG_TP0_CHICKEN;
873 *cmds++ = tmp_ctx.chicken_restore;
Jordan Crousea78c9172011-07-11 13:14:09 -0600874
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700875 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
876 *cmds++ = 0;
877 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600878
879 /* Set TP0_CHICKEN to zero */
Jordan Crouse084427d2011-07-28 08:37:58 -0600880 *cmds++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600881 *cmds++ = 0x00000000;
882
883 /* Set PA_SC_AA_CONFIG to 0 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600884 *cmds++ = cp_type0_packet(REG_PA_SC_AA_CONFIG, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600885 *cmds++ = 0x00000000;
886 /* shader constants */
887
888 /* vertex buffer constants */
Jordan Crouse084427d2011-07-28 08:37:58 -0600889 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 7);
Jordan Crousea78c9172011-07-11 13:14:09 -0600890
891 *cmds++ = (0x1 << 16) | (9 * 6);
892 /* valid(?) vtx constant flag & addr */
893 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
894 /* limit = 12 dwords */
895 *cmds++ = 0x00000030;
896 /* valid(?) vtx constant flag & addr */
897 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
898 /* limit = 8 dwords */
899 *cmds++ = 0x00000020;
900 *cmds++ = 0;
901 *cmds++ = 0;
902
903 /* Invalidate L2 cache to make sure vertices are updated */
Jordan Crouse084427d2011-07-28 08:37:58 -0600904 *cmds++ = cp_type0_packet(REG_TC_CNTL_STATUS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -0600905 *cmds++ = 0x1;
906
907 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
908
Tarun Karra16346b02011-07-24 15:04:26 -0700909 /* Repartition shaders */
Jordan Crouse084427d2011-07-28 08:37:58 -0600910 *cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jeremy Gebben72aadf42011-12-02 11:00:49 -0700911 *cmds++ = adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700912
913 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -0600914 *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Tarun Karra16346b02011-07-24 15:04:26 -0700915 *cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
916
Jordan Crouse084427d2011-07-28 08:37:58 -0600917 *cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jeremy Gebbenddf6b572011-09-09 13:39:49 -0700918 *cmds++ = adreno_encode_istore_size(adreno_dev)
919 | adreno_dev->pix_shader_start;
Tarun Karra16346b02011-07-24 15:04:26 -0700920
Jordan Crousea78c9172011-07-11 13:14:09 -0600921 /* Load the patched fragment shader stream */
922 cmds =
923 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
924
925 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
Jordan Crouse084427d2011-07-28 08:37:58 -0600926 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600927 *cmds++ = CP_REG(REG_SQ_PROGRAM_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600928 *cmds++ = 0x10030002;
929 *cmds++ = 0x00000008;
930
Jordan Crouse084427d2011-07-28 08:37:58 -0600931 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600932 *cmds++ = CP_REG(REG_PA_SC_AA_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -0600933 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
934
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -0600935 if (!adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -0600936 /* PA_SC_VIZ_QUERY */
Jordan Crouse084427d2011-07-28 08:37:58 -0600937 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600938 *cmds++ = CP_REG(REG_PA_SC_VIZ_QUERY);
Jordan Crousea78c9172011-07-11 13:14:09 -0600939 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
940 }
941
942 /* RB_COLORCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600943 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600944 *cmds++ = CP_REG(REG_RB_COLORCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600945 *cmds++ = 0x00000c20;
946
Jordan Crouse084427d2011-07-28 08:37:58 -0600947 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 4);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600948 *cmds++ = CP_REG(REG_VGT_MAX_VTX_INDX);
Jordan Crousea78c9172011-07-11 13:14:09 -0600949 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
950 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
951 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
952
Jordan Crouse084427d2011-07-28 08:37:58 -0600953 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600954 *cmds++ = CP_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600955 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
956 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
957
Jordan Crouse084427d2011-07-28 08:37:58 -0600958 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600959 *cmds++ = CP_REG(REG_SQ_INTERPOLATOR_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600960 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
961
Jordan Crouse084427d2011-07-28 08:37:58 -0600962 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600963 *cmds++ = CP_REG(REG_PA_SC_AA_CONFIG);
Jordan Crousea78c9172011-07-11 13:14:09 -0600964 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
965
966 /* set REG_PA_SU_SC_MODE_CNTL
967 * Front_ptype = draw triangles
968 * Back_ptype = draw triangles
969 * Provoking vertex = last
970 */
Jordan Crouse084427d2011-07-28 08:37:58 -0600971 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600972 *cmds++ = CP_REG(REG_PA_SU_SC_MODE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -0600973 *cmds++ = 0x00080240;
974
975 /* texture constants */
976 *cmds++ =
Jordan Crouse084427d2011-07-28 08:37:58 -0600977 cp_type3_packet(CP_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
Jordan Crousea78c9172011-07-11 13:14:09 -0600978 *cmds++ = (0x1 << 16) | (0 * 6);
979 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
980 cmds[0] |= (shadow->pitch >> 5) << 22;
981 cmds[1] |=
982 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
983 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
984 cmds += SYS2GMEM_TEX_CONST_LEN;
985
986 /* program surface info */
Jordan Crouse084427d2011-07-28 08:37:58 -0600987 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600988 *cmds++ = CP_REG(REG_RB_SURFACE_INFO);
Jordan Crousea78c9172011-07-11 13:14:09 -0600989 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
990
991 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
992 * Base=gmem_base
993 */
994 *cmds++ =
995 (shadow->
996 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
997
998 /* RB_DEPTHCONTROL */
Jordan Crouse084427d2011-07-28 08:37:58 -0600999 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001000 *cmds++ = CP_REG(REG_RB_DEPTHCONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001001
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001002 if (adreno_is_a22x(adreno_dev))
Jordan Crousea78c9172011-07-11 13:14:09 -06001003 *cmds++ = 8; /* disable Z */
1004 else
1005 *cmds++ = 0; /* disable Z */
1006
1007 /* Use maximum scissor values -- quad vertices already
1008 * have the correct bounds */
Jordan Crouse084427d2011-07-28 08:37:58 -06001009 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001010 *cmds++ = CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001011 *cmds++ = (0 << 16) | 0;
1012 *cmds++ = ((0x1fff) << 16) | 0x1fff;
Jordan Crouse084427d2011-07-28 08:37:58 -06001013 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001014 *cmds++ = CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001015 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
1016 *cmds++ = ((0x1fff) << 16) | 0x1fff;
1017
Jordan Crouse084427d2011-07-28 08:37:58 -06001018 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001019 *cmds++ = CP_REG(REG_PA_CL_VTE_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001020 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
1021 *cmds++ = 0x00000b00;
1022
1023 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
Jordan Crouse084427d2011-07-28 08:37:58 -06001024 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001025 *cmds++ = CP_REG(REG_PA_CL_VPORT_ZSCALE);
Jordan Crousea78c9172011-07-11 13:14:09 -06001026 *cmds++ = 0xbf800000;
1027 *cmds++ = 0x0;
1028
Jordan Crouse084427d2011-07-28 08:37:58 -06001029 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001030 *cmds++ = CP_REG(REG_RB_COLOR_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001031 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
1032
Jordan Crouse084427d2011-07-28 08:37:58 -06001033 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001034 *cmds++ = CP_REG(REG_RB_COLOR_DEST_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001035 *cmds++ = 0xffffffff;
1036
Jordan Crouse084427d2011-07-28 08:37:58 -06001037 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 3);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001038 *cmds++ = CP_REG(REG_SQ_WRAPPING_0);
Jordan Crousea78c9172011-07-11 13:14:09 -06001039 *cmds++ = 0x00000000;
1040 *cmds++ = 0x00000000;
1041
1042 /* load the stencil ref value
1043 * $AAM - do this later
1044 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001045 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001046 *cmds++ = CP_REG(REG_RB_MODECONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001047 /* draw pixels with color and depth/stencil component */
1048 *cmds++ = 0x4;
1049
Jordan Crouse084427d2011-07-28 08:37:58 -06001050 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001051 *cmds++ = CP_REG(REG_PA_CL_CLIP_CNTL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001052 *cmds++ = 0x00010000;
1053
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001054 if (adreno_is_a22x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001055 *cmds++ = cp_type3_packet(CP_SET_DRAW_INIT_FLAGS, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001056 *cmds++ = 0;
1057
Jordan Crouse084427d2011-07-28 08:37:58 -06001058 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001059 *cmds++ = CP_REG(REG_A220_RB_LRZ_VSC_CONTROL);
Jordan Crousea78c9172011-07-11 13:14:09 -06001060 *cmds++ = 0x0000000;
1061
Jordan Crouse084427d2011-07-28 08:37:58 -06001062 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001063 *cmds++ = 0; /* viz query info. */
1064 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
1065 *cmds++ = 0x00004088;
1066 *cmds++ = 3; /* NumIndices=3 */
1067 } else {
1068 /* queue the draw packet */
Jordan Crouse084427d2011-07-28 08:37:58 -06001069 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001070 *cmds++ = 0; /* viz query info. */
1071 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
1072 *cmds++ = 0x00030088;
1073 }
1074
1075 /* create indirect buffer command for above command sequence */
1076 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
1077
1078 return cmds;
1079}
1080
Jordan Crousea78c9172011-07-11 13:14:09 -06001081static void build_regrestore_cmds(struct adreno_device *adreno_dev,
1082 struct adreno_context *drawctxt)
1083{
1084 unsigned int *start = tmp_ctx.cmd;
1085 unsigned int *cmd = start;
1086
1087 unsigned int i = 0;
1088 unsigned int reg_array_size = 0;
1089 const unsigned int *ptr_register_ranges;
1090
Jordan Crouse084427d2011-07-28 08:37:58 -06001091 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001092 *cmd++ = 0;
1093
1094 /* H/W Registers */
Jordan Crouse084427d2011-07-28 08:37:58 -06001095 /* deferred cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, ???); */
Jordan Crousea78c9172011-07-11 13:14:09 -06001096 cmd++;
1097#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1098 /* Force mismatch */
1099 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1100#else
1101 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1102#endif
1103
1104 /* Based on chip id choose the registers ranges*/
Jeremy Gebben99105cb2011-08-31 10:23:05 -07001105 if (adreno_is_a220(adreno_dev)) {
1106 ptr_register_ranges = register_ranges_a220;
1107 reg_array_size = ARRAY_SIZE(register_ranges_a220);
1108 } else if (adreno_is_a225(adreno_dev)) {
1109 ptr_register_ranges = register_ranges_a225;
1110 reg_array_size = ARRAY_SIZE(register_ranges_a225);
Jordan Crousea78c9172011-07-11 13:14:09 -06001111 } else {
1112 ptr_register_ranges = register_ranges_a20x;
1113 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1114 }
1115
1116
1117 for (i = 0; i < (reg_array_size/2); i++) {
1118 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1119 ptr_register_ranges[i*2+1]);
1120 }
1121
1122 /* Now we know how many register blocks we have, we can compute command
1123 * length
1124 */
1125 start[2] =
Jordan Crouse084427d2011-07-28 08:37:58 -06001126 cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001127 /* Enable shadowing for the entire register block. */
1128#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1129 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1130#else
1131 start[4] |= (1 << 24) | (4 << 16);
1132#endif
1133
1134 /* Need to handle some of the registers separately */
Jordan Crouse084427d2011-07-28 08:37:58 -06001135 *cmd++ = cp_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001136 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1137 *cmd++ = 0x00040400;
1138
Jordan Crouse084427d2011-07-28 08:37:58 -06001139 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001140 *cmd++ = 0;
Jordan Crouse084427d2011-07-28 08:37:58 -06001141 *cmd++ = cp_type0_packet(REG_TP0_CHICKEN, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001142 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1143 *cmd++ = 0x00000000;
1144
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001145 if (adreno_is_a22x(adreno_dev)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001146 unsigned int i;
1147 unsigned int j = 2;
Jeremy Gebbeneebc4612011-08-31 10:15:21 -07001148 for (i = REG_A220_VSC_BIN_SIZE; i <=
1149 REG_A220_VSC_PIPE_DATA_LENGTH_7; i++) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001150 *cmd++ = cp_type0_packet(i, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001151 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1152 &drawctxt->gpustate);
1153 *cmd++ = 0x00000000;
1154 j++;
1155 }
1156 }
1157
1158 /* ALU Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001159 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001160 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1161#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1162 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1163#else
1164 *cmd++ = (1 << 24) | (0 << 16) | 0;
1165#endif
1166 *cmd++ = ALU_CONSTANTS;
1167
1168 /* Texture Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001169 *cmd++ = cp_type3_packet(CP_LOAD_CONSTANT_CONTEXT, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001170 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1171#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1172 /* Disable shadowing */
1173 *cmd++ = (0 << 24) | (1 << 16) | 0;
1174#else
1175 *cmd++ = (1 << 24) | (1 << 16) | 0;
1176#endif
1177 *cmd++ = TEX_CONSTANTS;
1178
1179 /* Boolean Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001180 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + BOOL_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001181 *cmd++ = (2 << 16) | 0;
1182
1183 /* the next BOOL_CONSTANT dwords is the shadow area for
1184 * boolean constants.
1185 */
1186 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1187 cmd += BOOL_CONSTANTS;
1188
1189 /* Loop Constants */
Jordan Crouse084427d2011-07-28 08:37:58 -06001190 *cmd++ = cp_type3_packet(CP_SET_CONSTANT, 1 + LOOP_CONSTANTS);
Jordan Crousea78c9172011-07-11 13:14:09 -06001191 *cmd++ = (3 << 16) | 0;
1192
1193 /* the next LOOP_CONSTANTS dwords is the shadow area for
1194 * loop constants.
1195 */
1196 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1197 cmd += LOOP_CONSTANTS;
1198
1199 /* create indirect buffer command for above command sequence */
1200 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1201
1202 tmp_ctx.cmd = cmd;
1203}
1204
Jordan Crousea78c9172011-07-11 13:14:09 -06001205static void
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001206build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
1207 struct adreno_context *drawctxt)
Jordan Crousea78c9172011-07-11 13:14:09 -06001208{
1209 unsigned int *cmd = tmp_ctx.cmd;
1210 unsigned int *save, *restore, *fixup;
Jordan Crousea78c9172011-07-11 13:14:09 -06001211 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
Jordan Crousea78c9172011-07-11 13:14:09 -06001212 unsigned int *partition1;
1213 unsigned int *shaderBases, *partition2;
1214
Jordan Crousea78c9172011-07-11 13:14:09 -06001215 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1216 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001217 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
1218 + _shader_shadow_size(adreno_dev);
1219 tmp_ctx.shader_shared = tmp_ctx.shader_pixel
1220 + _shader_shadow_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001221
1222 /* restore shader partitioning and instructions */
1223
1224 restore = cmd; /* start address */
1225
1226 /* Invalidate Vertex & Pixel instruction code address and sizes */
Jordan Crouse084427d2011-07-28 08:37:58 -06001227 *cmd++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001228 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1229
1230 /* Restore previous shader vertex & pixel instruction bases. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001231 *cmd++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001232 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1233
1234 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001235 *cmd++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001236 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1237
Jordan Crousea78c9172011-07-11 13:14:09 -06001238 /* load vertex 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_vertex + 0x0; /* 0x0 = Vertex */
1241 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1242
1243 /* load pixel 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_pixel + 0x1; /* 0x1 = Pixel */
1246 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1247
1248 /* load shared shader instructions from the shadow. */
Jordan Crouse084427d2011-07-28 08:37:58 -06001249 *cmd++ = cp_type3_packet(CP_IM_LOAD, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001250 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1251 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
Jordan Crousea78c9172011-07-11 13:14:09 -06001252
1253 /* create indirect buffer command for above command sequence */
1254 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1255
1256 /*
1257 * fixup SET_SHADER_BASES data
1258 *
1259 * since self-modifying PM4 code is being used here, a seperate
1260 * command buffer is used for this fixup operation, to ensure the
1261 * commands are not read by the PM4 engine before the data fields
1262 * have been written.
1263 */
1264
1265 fixup = cmd; /* start address */
1266
1267 /* write the shader partition information to a scratch register */
Jordan Crouse084427d2011-07-28 08:37:58 -06001268 *cmd++ = cp_type0_packet(REG_SCRATCH_REG2, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001269 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1270
1271 /* mask off unused bits, then OR with shader instruction memory size */
Jordan Crouse084427d2011-07-28 08:37:58 -06001272 *cmd++ = cp_type3_packet(CP_REG_RMW, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001273 *cmd++ = REG_SCRATCH_REG2;
1274 /* AND off invalid bits. */
1275 *cmd++ = 0x0FFF0FFF;
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001276 /* OR in instruction memory size. */
1277 *cmd++ = adreno_encode_istore_size(adreno_dev);
Jordan Crousea78c9172011-07-11 13:14:09 -06001278
1279 /* write the computed value to the SET_SHADER_BASES data field */
Jordan Crouse084427d2011-07-28 08:37:58 -06001280 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001281 *cmd++ = REG_SCRATCH_REG2;
1282 /* TBD #5: shader bases (to restore) */
1283 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1284
1285 /* create indirect buffer command for above command sequence */
1286 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1287
1288 /* save shader partitioning and instructions */
1289
1290 save = cmd; /* start address */
1291
Jordan Crouse084427d2011-07-28 08:37:58 -06001292 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001293 *cmd++ = 0;
1294
1295 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1296 * store the value in the data fields of the SET_CONSTANT commands
1297 * above.
1298 */
Jordan Crouse084427d2011-07-28 08:37:58 -06001299 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001300 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1301 /* TBD #4a: partition info (to restore) */
1302 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
Jordan Crouse084427d2011-07-28 08:37:58 -06001303 *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001304 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1305 /* TBD #4b: partition info (to fixup) */
1306 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1307
Jordan Crousea78c9172011-07-11 13:14:09 -06001308
1309 /* store the vertex shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001310 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001311 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1312 /* TBD #1: start/size (to restore) */
1313 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1314
1315 /* store the pixel shader instructions */
Jordan Crouse084427d2011-07-28 08:37:58 -06001316 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001317 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1318 /* TBD #2: start/size (to restore) */
1319 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1320
1321 /* store the shared shader instructions if vertex base is nonzero */
1322
Jordan Crouse084427d2011-07-28 08:37:58 -06001323 *cmd++ = cp_type3_packet(CP_IM_STORE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001324 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1325 /* TBD #3: start/size (to restore) */
1326 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1327
Jordan Crousea78c9172011-07-11 13:14:09 -06001328
Jordan Crouse084427d2011-07-28 08:37:58 -06001329 *cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001330 *cmd++ = 0;
1331
1332 /* create indirect buffer command for above command sequence */
1333 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1334
1335 tmp_ctx.cmd = cmd;
1336}
1337
1338/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001339static int a2xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001340 struct adreno_context *drawctxt)
1341{
Jordan Crousea78c9172011-07-11 13:14:09 -06001342 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1343
Jordan Crousea78c9172011-07-11 13:14:09 -06001344 /* build indirect command buffers to save & restore regs/constants */
Jordan Crousea78c9172011-07-11 13:14:09 -06001345 build_regrestore_cmds(adreno_dev, drawctxt);
1346 build_regsave_cmds(adreno_dev, drawctxt);
1347
Jeremy Gebbenddf6b572011-09-09 13:39:49 -07001348 build_shader_save_restore_cmds(adreno_dev, drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001349
Jordan Crousea78c9172011-07-11 13:14:09 -06001350 return 0;
1351}
1352
1353/* create buffers for saving/restoring registers, constants, & GMEM */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001354static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001355 struct adreno_context *drawctxt)
1356{
1357 int result;
1358
Anoop Kumar Yerukalaa4e88c62012-05-01 14:43:06 +05301359 calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size);
Jordan Crouse7501d452012-04-19 08:58:44 -06001360 tmp_ctx.gmem_base = adreno_dev->gmem_base;
Jordan Crousea78c9172011-07-11 13:14:09 -06001361
1362 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1363 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1364
1365 if (result)
1366 return result;
1367
Carter Cooperec549da2012-04-02 15:51:38 -06001368 /* set the gmem shadow flag for the context */
1369 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
Jordan Crousea78c9172011-07-11 13:14:09 -06001370
1371 /* blank out gmem shadow. */
1372 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1373 drawctxt->context_gmem_shadow.size);
1374
1375 /* build quad vertex buffer */
Jordan Crouse0e0486f2011-07-28 08:37:58 -06001376 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
1377 &tmp_ctx.cmd);
Jordan Crousea78c9172011-07-11 13:14:09 -06001378
1379 /* build TP0_CHICKEN register restore command buffer */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001380 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE))
1381 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
Jordan Crousea78c9172011-07-11 13:14:09 -06001382
1383 /* build indirect command buffers to save & restore gmem */
Jordan Crousea78c9172011-07-11 13:14:09 -06001384 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1385 tmp_ctx.cmd =
1386 build_gmem2sys_cmds(adreno_dev, drawctxt,
1387 &drawctxt->context_gmem_shadow);
1388 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1389 tmp_ctx.cmd =
1390 build_sys2gmem_cmds(adreno_dev, drawctxt,
1391 &drawctxt->context_gmem_shadow);
1392
1393 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1394 KGSL_CACHE_OP_FLUSH);
1395
Sushmita Susheelendraf3896062011-08-12 16:33:10 -06001396 kgsl_cffdump_syncmem(NULL,
1397 &drawctxt->context_gmem_shadow.gmemshadow,
1398 drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
1399 drawctxt->context_gmem_shadow.gmemshadow.size, false);
1400
Jordan Crousea78c9172011-07-11 13:14:09 -06001401 return 0;
1402}
1403
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001404static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
1405 struct adreno_context *drawctxt)
1406{
1407 int ret;
1408
1409 /*
1410 * Allocate memory for the GPU state and the context commands.
1411 * Despite the name, this is much more then just storage for
1412 * the gpustate. This contains command space for gmem save
1413 * and texture and vertex buffer storage too
1414 */
1415
1416 ret = kgsl_allocate(&drawctxt->gpustate,
1417 drawctxt->pagetable, _context_size(adreno_dev));
1418
1419 if (ret)
1420 return ret;
1421
1422 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
1423 _context_size(adreno_dev));
1424
1425 tmp_ctx.cmd = tmp_ctx.start
1426 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1427
1428 if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
1429 ret = a2xx_create_gpustate_shadow(adreno_dev, drawctxt);
1430 if (ret)
1431 goto done;
1432
1433 drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
1434 }
1435
1436 if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
1437 ret = a2xx_create_gmem_shadow(adreno_dev, drawctxt);
1438 if (ret)
1439 goto done;
1440 }
1441
1442 /* Flush and sync the gpustate memory */
1443
1444 kgsl_cache_range_op(&drawctxt->gpustate,
1445 KGSL_CACHE_OP_FLUSH);
1446
1447 kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
1448 drawctxt->gpustate.gpuaddr,
1449 drawctxt->gpustate.size, false);
1450
1451done:
1452 if (ret)
1453 kgsl_sharedmem_free(&drawctxt->gpustate);
1454
1455 return ret;
1456}
1457
1458static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001459 struct adreno_context *context)
1460{
1461 struct kgsl_device *device = &adreno_dev->dev;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001462 unsigned int cmd[22];
Jordan Crousea78c9172011-07-11 13:14:09 -06001463
1464 if (context == NULL)
1465 return;
1466
1467 if (context->flags & CTXT_FLAGS_GPU_HANG)
1468 KGSL_CTXT_WARN(device,
1469 "Current active context has caused gpu hang\n");
1470
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001471 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001472
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001473 /* save registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001474 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001475 context->reg_save, 3);
Jordan Crousea78c9172011-07-11 13:14:09 -06001476
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001477 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1478 /* save shader partitioning and instructions. */
1479 adreno_ringbuffer_issuecmds(device,
1480 KGSL_CMD_FLAGS_PMODE,
1481 context->shader_save, 3);
1482
1483 /*
1484 * fixup shader partitioning parameter for
1485 * SET_SHADER_BASES.
1486 */
1487 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1488 context->shader_fixup, 3);
1489
1490 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1491 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001492 }
1493
1494 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1495 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1496 /* save gmem.
1497 * (note: changes shader. shader must already be saved.)
1498 */
1499 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1500 context->context_gmem_shadow.gmem_save, 3);
1501
1502 /* Restore TP0_CHICKEN */
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001503 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1504 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1505 context->chicken_restore, 3);
1506 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001507
1508 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
Shubhraprakash Das3598b2e2011-11-22 15:07:16 -07001509 } else if (adreno_is_a225(adreno_dev)) {
1510 unsigned int *cmds = &cmd[0];
1511 /*
1512 * Issue an empty draw call to avoid possible hangs due to
1513 * repeated idles without intervening draw calls.
1514 * On adreno 225 the PC block has a cache that is only
1515 * flushed on draw calls and repeated idles can make it
1516 * overflow. The gmem save path contains draw calls so
1517 * this workaround isn't needed there.
1518 */
1519 *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
1520 *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
1521 *cmds++ = 0;
1522 *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
1523 *cmds++ = 0;
1524 *cmds++ = 1<<14;
1525 *cmds++ = 0;
1526 *cmds++ = device->mmu.setstate_memory.gpuaddr;
1527 *cmds++ = 0;
1528 *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
1529 *cmds++ = 0x00000000;
1530
1531 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1532 &cmd[0], 11);
Jordan Crousea78c9172011-07-11 13:14:09 -06001533 }
1534}
1535
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001536static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
Jordan Crousea78c9172011-07-11 13:14:09 -06001537 struct adreno_context *context)
1538{
1539 struct kgsl_device *device = &adreno_dev->dev;
1540 unsigned int cmds[5];
1541
1542 if (context == NULL) {
1543 /* No context - set the default apgetable and thats it */
Shubhraprakash Das79447952012-04-26 18:12:23 -06001544 kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
Jordan Crousea78c9172011-07-11 13:14:09 -06001545 return;
1546 }
1547
1548 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1549
Jordan Crouse084427d2011-07-28 08:37:58 -06001550 cmds[0] = cp_nop_packet(1);
Jordan Crousea78c9172011-07-11 13:14:09 -06001551 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
Jordan Crouse084427d2011-07-28 08:37:58 -06001552 cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
Jordan Crousea78c9172011-07-11 13:14:09 -06001553 cmds[3] = device->memstore.gpuaddr +
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001554 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
1555 cmds[4] = context->id;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001556 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
Shubhraprakash Das79447952012-04-26 18:12:23 -06001557 kgsl_mmu_setstate(&device->mmu, context->pagetable);
Jordan Crousea78c9172011-07-11 13:14:09 -06001558
1559#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1560 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1561 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1562 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1563#endif
1564
1565 /* restore gmem.
1566 * (note: changes shader. shader must not already be restored.)
1567 */
1568 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1569 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1570 context->context_gmem_shadow.gmem_restore, 3);
1571
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001572 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
1573 /* Restore TP0_CHICKEN */
1574 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1575 context->chicken_restore, 3);
1576 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001577
1578 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1579 }
1580
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001581 if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001582
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001583 /* restore registers and constants. */
Jordan Crousee0ea7622012-01-24 09:32:04 -07001584 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001585 context->reg_restore, 3);
1586
1587 /* restore shader instructions & partitioning. */
1588 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1589 adreno_ringbuffer_issuecmds(device,
1590 KGSL_CMD_FLAGS_NONE,
1591 context->shader_restore, 3);
1592 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001593 }
1594
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001595 if (adreno_is_a20x(adreno_dev)) {
Jordan Crouse084427d2011-07-28 08:37:58 -06001596 cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001597 cmds[1] = context->bin_base_offset;
Jordan Crousee0ea7622012-01-24 09:32:04 -07001598 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
1599 cmds, 2);
Jeremy Gebben5bb7ece2011-08-02 11:04:48 -06001600 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001601}
1602
1603/*
1604 * Interrupt management
1605 *
1606 * a2xx interrupt control is distributed among the various
1607 * hardware components (RB, CP, MMU). The main interrupt
1608 * tells us which component fired the interrupt, but one needs
1609 * to go to the individual component to find out why. The
1610 * following functions provide the broken out support for
1611 * managing the interrupts
1612 */
1613
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001614#define RBBM_INT_MASK RBBM_INT_CNTL__RDERR_INT_MASK
Jordan Crousea78c9172011-07-11 13:14:09 -06001615
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001616#define CP_INT_MASK \
1617 (CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001618 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1619 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1620 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1621 CP_INT_CNTL__IB_ERROR_MASK | \
Jordan Crousea78c9172011-07-11 13:14:09 -06001622 CP_INT_CNTL__IB1_INT_MASK | \
1623 CP_INT_CNTL__RB_INT_MASK)
1624
1625#define VALID_STATUS_COUNT_MAX 10
1626
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001627static struct {
1628 unsigned int mask;
1629 const char *message;
1630} kgsl_cp_error_irqs[] = {
1631 { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
1632 "ringbuffer TO packet in IB interrupt" },
1633 { CP_INT_CNTL__OPCODE_ERROR_MASK,
1634 "ringbuffer opcode error interrupt" },
1635 { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
1636 "ringbuffer protected mode error interrupt" },
1637 { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
1638 "ringbuffer reserved bit error interrupt" },
1639 { CP_INT_CNTL__IB_ERROR_MASK,
1640 "ringbuffer IB error interrupt" },
1641};
1642
Jordan Crousea78c9172011-07-11 13:14:09 -06001643static void a2xx_cp_intrcallback(struct kgsl_device *device)
1644{
1645 unsigned int status = 0, num_reads = 0, master_status = 0;
1646 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1647 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001648 int i;
Jordan Crousea78c9172011-07-11 13:14:09 -06001649
1650 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1651 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1652 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1653 adreno_regread(device, REG_CP_INT_STATUS, &status);
1654 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1655 &master_status);
1656 num_reads++;
1657 }
1658 if (num_reads > 1)
1659 KGSL_DRV_WARN(device,
1660 "Looped %d times to read REG_CP_INT_STATUS\n",
1661 num_reads);
Norman Geed7402ff2011-10-28 08:51:11 -06001662
1663 trace_kgsl_a2xx_irq_status(device, master_status, status);
1664
Jordan Crousea78c9172011-07-11 13:14:09 -06001665 if (!status) {
1666 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1667 /* This indicates that we could not read CP_INT_STAT.
1668 * As a precaution just wake up processes so
1669 * they can check their timestamps. Since, we
1670 * did not ack any interrupts this interrupt will
1671 * be generated again */
1672 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1673 wake_up_interruptible_all(&device->wait_queue);
1674 } else
1675 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1676 return;
1677 }
1678
1679 if (status & CP_INT_CNTL__RB_INT_MASK) {
1680 /* signal intr completion event */
Carter Cooper7e7f02e2012-02-15 09:36:31 -07001681 unsigned int context_id;
1682 kgsl_sharedmem_readl(&device->memstore,
1683 &context_id,
1684 KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
1685 current_context));
1686 if (context_id < KGSL_MEMSTORE_MAX) {
1687 kgsl_sharedmem_writel(&rb->device->memstore,
1688 KGSL_MEMSTORE_OFFSET(context_id,
1689 ts_cmp_enable), 0);
1690 device->last_expired_ctxt_id = context_id;
1691 wmb();
1692 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001693 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1694 }
1695
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001696 for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
1697 if (status & kgsl_cp_error_irqs[i].mask) {
1698 KGSL_CMD_CRIT(rb->device, "%s\n",
1699 kgsl_cp_error_irqs[i].message);
1700 /*
1701 * on fatal errors, turn off the interrupts to
1702 * avoid storming. This has the side effect of
1703 * forcing a PM dump when the timestamp times out
1704 */
Jordan Crousea78c9172011-07-11 13:14:09 -06001705
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001706 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1707 }
1708 }
Jordan Crousea78c9172011-07-11 13:14:09 -06001709
1710 /* only ack bits we understand */
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001711 status &= CP_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001712 adreno_regwrite(device, REG_CP_INT_ACK, status);
1713
1714 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1715 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
Jordan Crouse1bf80aa2011-10-12 16:57:47 -06001716 queue_work(device->work_queue, &device->ts_expired_ws);
Jordan Crousea78c9172011-07-11 13:14:09 -06001717 wake_up_interruptible_all(&device->wait_queue);
1718 atomic_notifier_call_chain(&(device->ts_notifier_list),
1719 device->id,
1720 NULL);
1721 }
1722}
1723
1724static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1725{
1726 unsigned int status = 0;
1727 unsigned int rderr = 0;
Jeremy Gebben22784c22012-03-07 16:02:08 -07001728 unsigned int addr = 0;
1729 const char *source;
Jordan Crousea78c9172011-07-11 13:14:09 -06001730
1731 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1732
1733 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
Jordan Crousea78c9172011-07-11 13:14:09 -06001734 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
Jeremy Gebben22784c22012-03-07 16:02:08 -07001735 source = (rderr & RBBM_READ_ERROR_REQUESTER)
1736 ? "host" : "cp";
1737 /* convert to dword address */
1738 addr = (rderr & RBBM_READ_ERROR_ADDRESS_MASK) >> 2;
1739
1740 /*
1741 * Log CP_INT_STATUS interrupts from the CP at a
1742 * lower level because they can happen frequently
1743 * and are worked around in a2xx_irq_handler.
1744 */
1745 if (addr == REG_CP_INT_STATUS &&
1746 rderr & RBBM_READ_ERROR_ERROR &&
1747 rderr & RBBM_READ_ERROR_REQUESTER)
Jordan Crousea78c9172011-07-11 13:14:09 -06001748 KGSL_DRV_WARN(device,
Jeremy Gebben22784c22012-03-07 16:02:08 -07001749 "rbbm read error interrupt: %s reg: %04X\n",
1750 source, addr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001751 else
1752 KGSL_DRV_CRIT(device,
Jeremy Gebben22784c22012-03-07 16:02:08 -07001753 "rbbm read error interrupt: %s reg: %04X\n",
1754 source, addr);
Jordan Crousea78c9172011-07-11 13:14:09 -06001755 }
1756
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001757 status &= RBBM_INT_MASK;
Jordan Crousea78c9172011-07-11 13:14:09 -06001758 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1759}
1760
1761irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1762{
1763 struct kgsl_device *device = &adreno_dev->dev;
1764 irqreturn_t result = IRQ_NONE;
1765 unsigned int status;
1766
1767 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1768
1769 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1770 kgsl_mh_intrcallback(device);
1771 result = IRQ_HANDLED;
1772 }
1773
1774 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1775 a2xx_cp_intrcallback(device);
1776 result = IRQ_HANDLED;
1777 }
1778
1779 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1780 a2xx_rbbm_intrcallback(device);
1781 result = IRQ_HANDLED;
1782 }
1783
1784 return result;
1785}
1786
1787static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1788{
1789 struct kgsl_device *device = &adreno_dev->dev;
1790
1791 if (state) {
Jordan Crousec8c9fcd2011-07-28 08:37:58 -06001792 adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
1793 adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
Jordan Crousea78c9172011-07-11 13:14:09 -06001794 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1795 } else {
1796 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1797 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1798 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1799 }
Jordan Crouseb58e61b2011-08-08 13:25:36 -06001800
1801 /* Force the writes to post before touching the IRQ line */
1802 wmb();
Jordan Crousea78c9172011-07-11 13:14:09 -06001803}
1804
Jordan Crouseb4d31bd2012-02-01 22:11:12 -07001805static void a2xx_rb_init(struct adreno_device *adreno_dev,
1806 struct adreno_ringbuffer *rb)
1807{
1808 unsigned int *cmds, cmds_gpu;
1809
1810 /* ME_INIT */
1811 cmds = adreno_ringbuffer_allocspace(rb, 19);
1812 cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
1813
1814 GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
1815 /* All fields present (bits 9:0) */
1816 GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff);
1817 /* Disable/Enable Real-Time Stream processing (present but ignored) */
1818 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1819 /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
1820 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1821
1822 GSL_RB_WRITE(cmds, cmds_gpu,
1823 SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO));
1824 GSL_RB_WRITE(cmds, cmds_gpu,
1825 SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET));
1826 GSL_RB_WRITE(cmds, cmds_gpu,
1827 SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX));
1828 GSL_RB_WRITE(cmds, cmds_gpu,
1829 SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL));
1830 GSL_RB_WRITE(cmds, cmds_gpu,
1831 SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL));
1832 GSL_RB_WRITE(cmds, cmds_gpu,
1833 SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE));
1834 GSL_RB_WRITE(cmds, cmds_gpu,
1835 SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL));
1836 GSL_RB_WRITE(cmds, cmds_gpu,
1837 SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
1838
1839 /* Instruction memory size: */
1840 GSL_RB_WRITE(cmds, cmds_gpu,
1841 (adreno_encode_istore_size(adreno_dev)
1842 | adreno_dev->pix_shader_start));
1843 /* Maximum Contexts */
1844 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
1845 /* Write Confirm Interval and The CP will wait the
1846 * wait_interval * 16 clocks between polling */
1847 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1848
1849 /* NQ and External Memory Swap */
1850 GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
1851 /* Protected mode error checking */
1852 GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
1853 /* 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};