blob: b7a2bc95446a23e12b841061617a86592c3f51a6 [file] [log] [blame]
Jordan Crousea78c9172011-07-11 13:14:09 -06001/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include "kgsl.h"
15#include "kgsl_sharedmem.h"
16#include "kgsl_cffdump.h"
17#include "adreno.h"
18
19/*
20 *
21 * Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
22 * (34.5KB)
23 *
24 * +---------------------+------------+-------------+---+---------------------+
25 * | ALU Constant Shadow | Reg Shadow | C&V Buffers |Tex| Shader Instr Shadow |
26 * +---------------------+------------+-------------+---+---------------------+
27 * ________________________________/ \____________________
28 * / |
29 * +--------------+-----------+------+-----------+------------------------+
30 * | Restore Regs | Save Regs | Quad | Gmem Save | Gmem Restore | unused |
31 * +--------------+-----------+------+-----------+------------------------+
32 *
33 * 8K - ALU Constant Shadow (8K aligned)
34 * 4K - H/W Register Shadow (8K aligned)
35 * 4K - Command and Vertex Buffers
36 * - Indirect command buffer : Const/Reg restore
37 * - includes Loop & Bool const shadows
38 * - Indirect command buffer : Const/Reg save
39 * - Quad vertices & texture coordinates
40 * - Indirect command buffer : Gmem save
41 * - Indirect command buffer : Gmem restore
42 * - Unused (padding to 8KB boundary)
43 * <1K - Texture Constant Shadow (768 bytes) (8K aligned)
44 * 18K - Shader Instruction Shadow
45 * - 6K vertex (32 byte aligned)
46 * - 6K pixel (32 byte aligned)
47 * - 6K shared (32 byte aligned)
48 *
49 * Note: Reading constants into a shadow, one at a time using REG_TO_MEM, takes
50 * 3 DWORDS per DWORD transfered, plus 1 DWORD for the shadow, for a total of
51 * 16 bytes per constant. If the texture constants were transfered this way,
52 * the Command & Vertex Buffers section would extend past the 16K boundary.
53 * By moving the texture constant shadow area to start at 16KB boundary, we
54 * only require approximately 40 bytes more memory, but are able to use the
55 * LOAD_CONSTANT_CONTEXT shadowing feature for the textures, speeding up
56 * context switching.
57 *
58 * [Using LOAD_CONSTANT_CONTEXT shadowing feature for the Loop and/or Bool
59 * constants would require an additional 8KB each, for alignment.]
60 *
61 */
62
63/* Constants */
64
65#define ALU_CONSTANTS 2048 /* DWORDS */
66#define NUM_REGISTERS 1024 /* DWORDS */
67#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
68#define CMD_BUFFER_LEN 9216 /* DWORDS */
69#else
70#define CMD_BUFFER_LEN 3072 /* DWORDS */
71#endif
72#define TEX_CONSTANTS (32*6) /* DWORDS */
73#define BOOL_CONSTANTS 8 /* DWORDS */
74#define LOOP_CONSTANTS 56 /* DWORDS */
75#define SHADER_INSTRUCT_LOG2 9U /* 2^n == SHADER_INSTRUCTIONS */
76
77#if defined(PM4_IM_STORE)
78/* 96-bit instructions */
79#define SHADER_INSTRUCT (1<<SHADER_INSTRUCT_LOG2)
80#else
81#define SHADER_INSTRUCT 0
82#endif
83
84/* LOAD_CONSTANT_CONTEXT shadow size */
85#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
86
87#define ALU_SHADOW_SIZE LCC_SHADOW_SIZE /* 8KB */
88#define REG_SHADOW_SIZE 0x1000 /* 4KB */
89#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
90#define CMD_BUFFER_SIZE 0x9000 /* 36KB */
91#else
92#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
93#endif
94#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
95#define SHADER_SHADOW_SIZE (SHADER_INSTRUCT*12) /* 6KB */
96
97#define REG_OFFSET LCC_SHADOW_SIZE
98#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
99#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
100#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
101
102#define CONTEXT_SIZE (SHADER_OFFSET + 3 * SHADER_SHADOW_SIZE)
103
104/* A scratchpad used to build commands during context create */
105
106static struct tmp_ctx {
107 unsigned int *start; /* Command & Vertex buffer start */
108 unsigned int *cmd; /* Next available dword in C&V buffer */
109
110 /* address of buffers, needed when creating IB1 command buffers. */
111 uint32_t bool_shadow; /* bool constants */
112 uint32_t loop_shadow; /* loop constants */
113
114#if defined(PM4_IM_STORE)
115 uint32_t shader_shared; /* shared shader instruction shadow */
116 uint32_t shader_vertex; /* vertex shader instruction shadow */
117 uint32_t shader_pixel; /* pixel shader instruction shadow */
118#endif
119
120 /* Addresses in command buffer where separately handled registers
121 * are saved
122 */
123 uint32_t reg_values[33];
124 uint32_t chicken_restore;
125
126 uint32_t gmem_base; /* Base gpu address of GMEM */
127
128} tmp_ctx;
129
130/* context save (gmem -> sys) */
131
132/* pre-compiled vertex shader program
133*
134* attribute vec4 P;
135* void main(void)
136* {
137* gl_Position = P;
138* }
139*/
140#define GMEM2SYS_VTX_PGM_LEN 0x12
141
142static unsigned int gmem2sys_vtx_pgm[GMEM2SYS_VTX_PGM_LEN] = {
143 0x00011003, 0x00001000, 0xc2000000,
144 0x00001004, 0x00001000, 0xc4000000,
145 0x00001005, 0x00002000, 0x00000000,
146 0x1cb81000, 0x00398a88, 0x00000003,
147 0x140f803e, 0x00000000, 0xe2010100,
148 0x14000000, 0x00000000, 0xe2000000
149};
150
151/* pre-compiled fragment shader program
152*
153* precision highp float;
154* uniform vec4 clear_color;
155* void main(void)
156* {
157* gl_FragColor = clear_color;
158* }
159*/
160
161#define GMEM2SYS_FRAG_PGM_LEN 0x0c
162
163static unsigned int gmem2sys_frag_pgm[GMEM2SYS_FRAG_PGM_LEN] = {
164 0x00000000, 0x1002c400, 0x10000000,
165 0x00001003, 0x00002000, 0x00000000,
166 0x140f8000, 0x00000000, 0x22000000,
167 0x14000000, 0x00000000, 0xe2000000
168};
169
170/* context restore (sys -> gmem) */
171/* pre-compiled vertex shader program
172*
173* attribute vec4 position;
174* attribute vec4 texcoord;
175* varying vec4 texcoord0;
176* void main()
177* {
178* gl_Position = position;
179* texcoord0 = texcoord;
180* }
181*/
182
183#define SYS2GMEM_VTX_PGM_LEN 0x18
184
185static unsigned int sys2gmem_vtx_pgm[SYS2GMEM_VTX_PGM_LEN] = {
186 0x00052003, 0x00001000, 0xc2000000, 0x00001005,
187 0x00001000, 0xc4000000, 0x00001006, 0x10071000,
188 0x20000000, 0x18981000, 0x0039ba88, 0x00000003,
189 0x12982000, 0x40257b08, 0x00000002, 0x140f803e,
190 0x00000000, 0xe2010100, 0x140f8000, 0x00000000,
191 0xe2020200, 0x14000000, 0x00000000, 0xe2000000
192};
193
194/* pre-compiled fragment shader program
195*
196* precision mediump float;
197* uniform sampler2D tex0;
198* varying vec4 texcoord0;
199* void main()
200* {
201* gl_FragColor = texture2D(tex0, texcoord0.xy);
202* }
203*/
204
205#define SYS2GMEM_FRAG_PGM_LEN 0x0f
206
207static unsigned int sys2gmem_frag_pgm[SYS2GMEM_FRAG_PGM_LEN] = {
208 0x00011002, 0x00001000, 0xc4000000, 0x00001003,
209 0x10041000, 0x20000000, 0x10000001, 0x1ffff688,
210 0x00000002, 0x140f8000, 0x00000000, 0xe2000000,
211 0x14000000, 0x00000000, 0xe2000000
212};
213
214/* shader texture constants (sysmem -> gmem) */
215#define SYS2GMEM_TEX_CONST_LEN 6
216
217static unsigned int sys2gmem_tex_const[SYS2GMEM_TEX_CONST_LEN] = {
218 /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
219 * RFMode=ZeroClamp-1, Dim=1:2d
220 */
221 0x00000002, /* Pitch = TBD */
222
223 /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
224 * NearestClamp=1:OGL Mode
225 */
226 0x00000800, /* Address[31:12] = TBD */
227
228 /* Width, Height, EndianSwap=0:None */
229 0, /* Width & Height = TBD */
230
231 /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
232 * Mip=2:BaseMap
233 */
234 0 << 1 | 1 << 4 | 2 << 7 | 3 << 10 | 2 << 23,
235
236 /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
237 * Dim3d=0
238 */
239 0,
240
241 /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
242 * Dim=1:2d, MipPacking=0
243 */
244 1 << 9 /* Mip Address[31:12] = TBD */
245};
246
247/* quad for copying GMEM to context shadow */
248#define QUAD_LEN 12
249
250static unsigned int gmem_copy_quad[QUAD_LEN] = {
251 0x00000000, 0x00000000, 0x3f800000,
252 0x00000000, 0x00000000, 0x3f800000,
253 0x00000000, 0x00000000, 0x3f800000,
254 0x00000000, 0x00000000, 0x3f800000
255};
256
257#define TEXCOORD_LEN 8
258
259static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = {
260 0x00000000, 0x3f800000,
261 0x3f800000, 0x3f800000,
262 0x00000000, 0x00000000,
263 0x3f800000, 0x00000000
264};
265
266#define NUM_COLOR_FORMATS 13
267
268static enum SURFACEFORMAT surface_format_table[NUM_COLOR_FORMATS] = {
269 FMT_4_4_4_4, /* COLORX_4_4_4_4 */
270 FMT_1_5_5_5, /* COLORX_1_5_5_5 */
271 FMT_5_6_5, /* COLORX_5_6_5 */
272 FMT_8, /* COLORX_8 */
273 FMT_8_8, /* COLORX_8_8 */
274 FMT_8_8_8_8, /* COLORX_8_8_8_8 */
275 FMT_8_8_8_8, /* COLORX_S8_8_8_8 */
276 FMT_16_FLOAT, /* COLORX_16_FLOAT */
277 FMT_16_16_FLOAT, /* COLORX_16_16_FLOAT */
278 FMT_16_16_16_16_FLOAT, /* COLORX_16_16_16_16_FLOAT */
279 FMT_32_FLOAT, /* COLORX_32_FLOAT */
280 FMT_32_32_FLOAT, /* COLORX_32_32_FLOAT */
281 FMT_32_32_32_32_FLOAT, /* COLORX_32_32_32_32_FLOAT */
282};
283
284static unsigned int format2bytesperpixel[NUM_COLOR_FORMATS] = {
285 2, /* COLORX_4_4_4_4 */
286 2, /* COLORX_1_5_5_5 */
287 2, /* COLORX_5_6_5 */
288 1, /* COLORX_8 */
289 2, /* COLORX_8_8 8*/
290 4, /* COLORX_8_8_8_8 */
291 4, /* COLORX_S8_8_8_8 */
292 2, /* COLORX_16_FLOAT */
293 4, /* COLORX_16_16_FLOAT */
294 8, /* COLORX_16_16_16_16_FLOAT */
295 4, /* COLORX_32_FLOAT */
296 8, /* COLORX_32_32_FLOAT */
297 16, /* COLORX_32_32_32_32_FLOAT */
298};
299
300/* shader linkage info */
301#define SHADER_CONST_ADDR (11 * 6 + 3)
302
303/* gmem command buffer length */
304#define PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg)))
305
306/* functions */
307static void config_gmemsize(struct gmem_shadow_t *shadow, int gmem_size)
308{
309 int w = 64, h = 64; /* 16KB surface, minimum */
310
311 shadow->format = COLORX_8_8_8_8;
312 /* convert from bytes to 32-bit words */
313 gmem_size = (gmem_size + 3) / 4;
314
315 /* find the right surface size, close to a square. */
316 while (w * h < gmem_size)
317 if (w < h)
318 w *= 2;
319 else
320 h *= 2;
321
322 shadow->width = w;
323 shadow->pitch = w;
324 shadow->height = h;
325 shadow->gmem_pitch = shadow->pitch;
326
327 shadow->size = shadow->pitch * shadow->height * 4;
328}
329
330static unsigned int *program_shader(unsigned int *cmds, int vtxfrag,
331 unsigned int *shader_pgm, int dwords)
332{
333 /* load the patched vertex shader stream */
334 *cmds++ = pm4_type3_packet(PM4_IM_LOAD_IMMEDIATE, 2 + dwords);
335 /* 0=vertex shader, 1=fragment shader */
336 *cmds++ = vtxfrag;
337 /* instruction start & size (in 32-bit words) */
338 *cmds++ = ((0 << 16) | dwords);
339
340 memcpy(cmds, shader_pgm, dwords << 2);
341 cmds += dwords;
342
343 return cmds;
344}
345
346static unsigned int *reg_to_mem(unsigned int *cmds, uint32_t dst,
347 uint32_t src, int dwords)
348{
349 while (dwords-- > 0) {
350 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
351 *cmds++ = src++;
352 *cmds++ = dst;
353 dst += 4;
354 }
355
356 return cmds;
357}
358
359#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
360
361static void build_reg_to_mem_range(unsigned int start, unsigned int end,
362 unsigned int **cmd,
363 struct adreno_context *drawctxt)
364{
365 unsigned int i = start;
366
367 for (i = start; i <= end; i++) {
368 *(*cmd)++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
369 *(*cmd)++ = i;
370 *(*cmd)++ =
371 ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) +
372 (i - 0x2000) * 4;
373 }
374}
375
376#endif
377
378/* chicken restore */
379static unsigned int *build_chicken_restore_cmds(
380 struct adreno_context *drawctxt)
381{
382 unsigned int *start = tmp_ctx.cmd;
383 unsigned int *cmds = start;
384
385 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
386 *cmds++ = 0;
387
388 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
389 tmp_ctx.chicken_restore = virt2gpu(cmds, &drawctxt->gpustate);
390 *cmds++ = 0x00000000;
391
392 /* create indirect buffer command for above command sequence */
393 create_ib1(drawctxt, drawctxt->chicken_restore, start, cmds);
394
395 return cmds;
396}
397
398/****************************************************************************/
399/* context save */
400/****************************************************************************/
401
402static const unsigned int register_ranges_a20x[] = {
403 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
404 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
405 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
406 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
407 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
408 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
409 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
410 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
411 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
412 REG_VGT_MAX_VTX_INDX, REG_RB_FOG_COLOR,
413 REG_RB_DEPTHCONTROL, REG_RB_MODECONTROL,
414 REG_PA_SU_POINT_SIZE, REG_PA_SC_LINE_STIPPLE,
415 REG_PA_SC_VIZ_QUERY, REG_PA_SC_VIZ_QUERY,
416 REG_VGT_VERTEX_REUSE_BLOCK_CNTL, REG_RB_DEPTH_CLEAR
417};
418
419static const unsigned int register_ranges_a22x[] = {
420 REG_RB_SURFACE_INFO, REG_RB_DEPTH_INFO,
421 REG_COHER_DEST_BASE_0, REG_PA_SC_SCREEN_SCISSOR_BR,
422 REG_PA_SC_WINDOW_OFFSET, REG_PA_SC_WINDOW_SCISSOR_BR,
423 REG_RB_STENCILREFMASK_BF, REG_PA_CL_VPORT_ZOFFSET,
424 REG_SQ_PROGRAM_CNTL, REG_SQ_WRAPPING_1,
425 REG_PA_SC_LINE_CNTL, REG_SQ_PS_CONST,
426 REG_PA_SC_AA_MASK, REG_PA_SC_AA_MASK,
427 REG_RB_SAMPLE_COUNT_CTL, REG_RB_COLOR_DEST_MASK,
428 REG_PA_SU_POLY_OFFSET_FRONT_SCALE, REG_PA_SU_POLY_OFFSET_BACK_OFFSET,
429 /* all the below registers are specific to Leia */
430 REG_LEIA_PC_MAX_VTX_INDX, REG_LEIA_PC_INDX_OFFSET,
431 REG_RB_COLOR_MASK, REG_RB_FOG_COLOR,
432 REG_RB_DEPTHCONTROL, REG_RB_COLORCONTROL,
433 REG_PA_CL_CLIP_CNTL, REG_PA_CL_VTE_CNTL,
434 REG_RB_MODECONTROL, REG_RB_SAMPLE_POS,
435 REG_PA_SU_POINT_SIZE, REG_PA_SU_LINE_CNTL,
436 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
437 REG_LEIA_PC_VERTEX_REUSE_BLOCK_CNTL,
438 REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR
439};
440
441
442/* save h/w regs, alu constants, texture contants, etc. ...
443* requires: bool_shadow_gpuaddr, loop_shadow_gpuaddr
444*/
445static void build_regsave_cmds(struct adreno_device *adreno_dev,
446 struct adreno_context *drawctxt)
447{
448 unsigned int *start = tmp_ctx.cmd;
449 unsigned int *cmd = start;
450
451 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
452 *cmd++ = 0;
453
454#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
455 /* Make sure the HW context has the correct register values
456 * before reading them. */
457 *cmd++ = pm4_type3_packet(PM4_CONTEXT_UPDATE, 1);
458 *cmd++ = 0;
459
460 {
461 unsigned int i = 0;
462 unsigned int reg_array_size = 0;
463 const unsigned int *ptr_register_ranges;
464
465 /* Based on chip id choose the register ranges */
466 if (adreno_is_a220(adreno_dev)) {
467 ptr_register_ranges = register_ranges_a22x;
468 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
469 } else {
470 ptr_register_ranges = register_ranges_a20x;
471 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
472 }
473
474
475 /* Write HW registers into shadow */
476 for (i = 0; i < (reg_array_size/2) ; i++) {
477 build_reg_to_mem_range(ptr_register_ranges[i*2],
478 ptr_register_ranges[i*2+1],
479 &cmd, drawctxt);
480 }
481 }
482
483 /* Copy ALU constants */
484 cmd =
485 reg_to_mem(cmd, (drawctxt->gpustate.gpuaddr) & 0xFFFFE000,
486 REG_SQ_CONSTANT_0, ALU_CONSTANTS);
487
488 /* Copy Tex constants */
489 cmd =
490 reg_to_mem(cmd,
491 (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000,
492 REG_SQ_FETCH_0, TEX_CONSTANTS);
493#else
494
495 /* Insert a wait for idle packet before reading the registers.
496 * This is to fix a hang/reset seen during stress testing. In this
497 * hang, CP encountered a timeout reading SQ's boolean constant
498 * register. There is logic in the HW that blocks reading of this
499 * register when the SQ block is not idle, which we believe is
500 * contributing to the hang.*/
501 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
502 *cmd++ = 0;
503
504 /* H/w registers are already shadowed; just need to disable shadowing
505 * to prevent corruption.
506 */
507 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
508 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
509 *cmd++ = 4 << 16; /* regs, start=0 */
510 *cmd++ = 0x0; /* count = 0 */
511
512 /* ALU constants are already shadowed; just need to disable shadowing
513 * to prevent corruption.
514 */
515 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
516 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
517 *cmd++ = 0 << 16; /* ALU, start=0 */
518 *cmd++ = 0x0; /* count = 0 */
519
520 /* Tex constants are already shadowed; just need to disable shadowing
521 * to prevent corruption.
522 */
523 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
524 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
525 *cmd++ = 1 << 16; /* Tex, start=0 */
526 *cmd++ = 0x0; /* count = 0 */
527#endif
528
529 /* Need to handle some of the registers separately */
530 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
531 *cmd++ = REG_SQ_GPR_MANAGEMENT;
532 *cmd++ = tmp_ctx.reg_values[0];
533
534 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
535 *cmd++ = REG_TP0_CHICKEN;
536 *cmd++ = tmp_ctx.reg_values[1];
537
538 if (adreno_is_a220(adreno_dev)) {
539 unsigned int i;
540 unsigned int j = 2;
541 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
542 REG_LEIA_VSC_PIPE_DATA_LENGTH_7; i++) {
543 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
544 *cmd++ = i;
545 *cmd++ = tmp_ctx.reg_values[j];
546 j++;
547 }
548 }
549
550 /* Copy Boolean constants */
551 cmd = reg_to_mem(cmd, tmp_ctx.bool_shadow, REG_SQ_CF_BOOLEANS,
552 BOOL_CONSTANTS);
553
554 /* Copy Loop constants */
555 cmd = reg_to_mem(cmd, tmp_ctx.loop_shadow,
556 REG_SQ_CF_LOOP, LOOP_CONSTANTS);
557
558 /* create indirect buffer command for above command sequence */
559 create_ib1(drawctxt, drawctxt->reg_save, start, cmd);
560
561 tmp_ctx.cmd = cmd;
562}
563
564/*copy colour, depth, & stencil buffers from graphics memory to system memory*/
565static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
566 struct adreno_context *drawctxt,
567 struct gmem_shadow_t *shadow)
568{
569 unsigned int *cmds = shadow->gmem_save_commands;
570 unsigned int *start = cmds;
571 /* Calculate the new offset based on the adjusted base */
572 unsigned int bytesperpixel = format2bytesperpixel[shadow->format];
573 unsigned int addr = shadow->gmemshadow.gpuaddr;
574 unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
575
576 /* Store TP0_CHICKEN register */
577 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
578 *cmds++ = REG_TP0_CHICKEN;
579
580 *cmds++ = tmp_ctx.chicken_restore;
581
582 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
583 *cmds++ = 0;
584
585 /* Set TP0_CHICKEN to zero */
586 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
587 *cmds++ = 0x00000000;
588
589 /* Set PA_SC_AA_CONFIG to 0 */
590 *cmds++ = pm4_type0_packet(REG_PA_SC_AA_CONFIG, 1);
591 *cmds++ = 0x00000000;
592
593 /* program shader */
594
595 /* load shader vtx constants ... 5 dwords */
596 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
597 *cmds++ = (0x1 << 16) | SHADER_CONST_ADDR;
598 *cmds++ = 0;
599 /* valid(?) vtx constant flag & addr */
600 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
601 /* limit = 12 dwords */
602 *cmds++ = 0x00000030;
603
604 /* Invalidate L2 cache to make sure vertices are updated */
605 *cmds++ = pm4_type0_packet(REG_TC_CNTL_STATUS, 1);
606 *cmds++ = 0x1;
607
608 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
609 *cmds++ = PM4_REG(REG_VGT_MAX_VTX_INDX);
610 *cmds++ = 0x00ffffff; /* REG_VGT_MAX_VTX_INDX */
611 *cmds++ = 0x0; /* REG_VGT_MIN_VTX_INDX */
612 *cmds++ = 0x00000000; /* REG_VGT_INDX_OFFSET */
613
614 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
615 *cmds++ = PM4_REG(REG_PA_SC_AA_MASK);
616 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
617
618 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
619 *cmds++ = PM4_REG(REG_RB_COLORCONTROL);
620 *cmds++ = 0x00000c20;
621
622 /* load the patched vertex shader stream */
623 cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
624
625 /* Load the patched fragment shader stream */
626 cmds =
627 program_shader(cmds, 1, gmem2sys_frag_pgm, GMEM2SYS_FRAG_PGM_LEN);
628
629 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
630 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
631 *cmds++ = PM4_REG(REG_SQ_PROGRAM_CNTL);
632 if (adreno_is_a220(adreno_dev))
633 *cmds++ = 0x10018001;
634 else
635 *cmds++ = 0x10010001;
636 *cmds++ = 0x00000008;
637
638 /* resolve */
639
640 /* PA_CL_VTE_CNTL */
641 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
642 *cmds++ = PM4_REG(REG_PA_CL_VTE_CNTL);
643 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
644 *cmds++ = 0x00000b00;
645
646 /* program surface info */
647 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
648 *cmds++ = PM4_REG(REG_RB_SURFACE_INFO);
649 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
650
651 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
652 * Base=gmem_base
653 */
654 /* gmem base assumed 4K aligned. */
655 BUG_ON(tmp_ctx.gmem_base & 0xFFF);
656 *cmds++ =
657 (shadow->
658 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
659
660 /* disable Z */
661 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
662 *cmds++ = PM4_REG(REG_RB_DEPTHCONTROL);
663 if (adreno_is_a220(adreno_dev))
664 *cmds++ = 0x08;
665 else
666 *cmds++ = 0;
667
668 /* set REG_PA_SU_SC_MODE_CNTL
669 * Front_ptype = draw triangles
670 * Back_ptype = draw triangles
671 * Provoking vertex = last
672 */
673 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
674 *cmds++ = PM4_REG(REG_PA_SU_SC_MODE_CNTL);
675 *cmds++ = 0x00080240;
676
677 /* Use maximum scissor values -- quad vertices already have the
678 * correct bounds */
679 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
680 *cmds++ = PM4_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
681 *cmds++ = (0 << 16) | 0;
682 *cmds++ = (0x1fff << 16) | (0x1fff);
683 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
684 *cmds++ = PM4_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
685 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
686 *cmds++ = (0x1fff << 16) | (0x1fff);
687
688 /* load the viewport so that z scale = clear depth and
689 * z offset = 0.0f
690 */
691 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
692 *cmds++ = PM4_REG(REG_PA_CL_VPORT_ZSCALE);
693 *cmds++ = 0xbf800000; /* -1.0f */
694 *cmds++ = 0x0;
695
696 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
697 *cmds++ = PM4_REG(REG_RB_COLOR_MASK);
698 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
699
700 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
701 *cmds++ = PM4_REG(REG_RB_COLOR_DEST_MASK);
702 *cmds++ = 0xffffffff;
703
704 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
705 *cmds++ = PM4_REG(REG_SQ_WRAPPING_0);
706 *cmds++ = 0x00000000;
707 *cmds++ = 0x00000000;
708
709 /* load the stencil ref value
710 * $AAM - do this later
711 */
712
713 /* load the COPY state */
714 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 6);
715 *cmds++ = PM4_REG(REG_RB_COPY_CONTROL);
716 *cmds++ = 0; /* RB_COPY_CONTROL */
717 *cmds++ = addr & 0xfffff000; /* RB_COPY_DEST_BASE */
718 *cmds++ = shadow->pitch >> 5; /* RB_COPY_DEST_PITCH */
719
720 /* Endian=none, Linear, Format=RGBA8888,Swap=0,!Dither,
721 * MaskWrite:R=G=B=A=1
722 */
723 *cmds++ = 0x0003c008 |
724 (shadow->format << RB_COPY_DEST_INFO__COPY_DEST_FORMAT__SHIFT);
725 /* Make sure we stay in offsetx field. */
726 BUG_ON(offset & 0xfffff000);
727 *cmds++ = offset;
728
729 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
730 *cmds++ = PM4_REG(REG_RB_MODECONTROL);
731 *cmds++ = 0x6; /* EDRAM copy */
732
733 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
734 *cmds++ = PM4_REG(REG_PA_CL_CLIP_CNTL);
735 *cmds++ = 0x00010000;
736
737 if (adreno_is_a220(adreno_dev)) {
738 *cmds++ = pm4_type3_packet(PM4_SET_DRAW_INIT_FLAGS, 1);
739 *cmds++ = 0;
740
741 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
742 *cmds++ = PM4_REG(REG_LEIA_RB_LRZ_VSC_CONTROL);
743 *cmds++ = 0x0000000;
744
745 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 3);
746 *cmds++ = 0; /* viz query info. */
747 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
748 *cmds++ = 0x00004088;
749 *cmds++ = 3; /* NumIndices=3 */
750 } else {
751 /* queue the draw packet */
752 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2);
753 *cmds++ = 0; /* viz query info. */
754 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
755 *cmds++ = 0x00030088;
756 }
757
758 /* create indirect buffer command for above command sequence */
759 create_ib1(drawctxt, shadow->gmem_save, start, cmds);
760
761 return cmds;
762}
763
764/* context restore */
765
766/*copy colour, depth, & stencil buffers from system memory to graphics memory*/
767static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
768 struct adreno_context *drawctxt,
769 struct gmem_shadow_t *shadow)
770{
771 unsigned int *cmds = shadow->gmem_restore_commands;
772 unsigned int *start = cmds;
773
774 /* Store TP0_CHICKEN register */
775 *cmds++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
776 *cmds++ = REG_TP0_CHICKEN;
777 *cmds++ = tmp_ctx.chicken_restore;
778
779 *cmds++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
780 *cmds++ = 0;
781
782 /* Set TP0_CHICKEN to zero */
783 *cmds++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
784 *cmds++ = 0x00000000;
785
786 /* Set PA_SC_AA_CONFIG to 0 */
787 *cmds++ = pm4_type0_packet(REG_PA_SC_AA_CONFIG, 1);
788 *cmds++ = 0x00000000;
789 /* shader constants */
790
791 /* vertex buffer constants */
792 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 7);
793
794 *cmds++ = (0x1 << 16) | (9 * 6);
795 /* valid(?) vtx constant flag & addr */
796 *cmds++ = shadow->quad_vertices.gpuaddr | 0x3;
797 /* limit = 12 dwords */
798 *cmds++ = 0x00000030;
799 /* valid(?) vtx constant flag & addr */
800 *cmds++ = shadow->quad_texcoords.gpuaddr | 0x3;
801 /* limit = 8 dwords */
802 *cmds++ = 0x00000020;
803 *cmds++ = 0;
804 *cmds++ = 0;
805
806 /* Invalidate L2 cache to make sure vertices are updated */
807 *cmds++ = pm4_type0_packet(REG_TC_CNTL_STATUS, 1);
808 *cmds++ = 0x1;
809
810 cmds = program_shader(cmds, 0, sys2gmem_vtx_pgm, SYS2GMEM_VTX_PGM_LEN);
811
812 /* Load the patched fragment shader stream */
813 cmds =
814 program_shader(cmds, 1, sys2gmem_frag_pgm, SYS2GMEM_FRAG_PGM_LEN);
815
816 /* SQ_PROGRAM_CNTL / SQ_CONTEXT_MISC */
817 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
818 *cmds++ = PM4_REG(REG_SQ_PROGRAM_CNTL);
819 *cmds++ = 0x10030002;
820 *cmds++ = 0x00000008;
821
822 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
823 *cmds++ = PM4_REG(REG_PA_SC_AA_MASK);
824 *cmds++ = 0x0000ffff; /* REG_PA_SC_AA_MASK */
825
826 if (!adreno_is_a220(adreno_dev)) {
827 /* PA_SC_VIZ_QUERY */
828 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
829 *cmds++ = PM4_REG(REG_PA_SC_VIZ_QUERY);
830 *cmds++ = 0x0; /*REG_PA_SC_VIZ_QUERY */
831 }
832
833 /* RB_COLORCONTROL */
834 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
835 *cmds++ = PM4_REG(REG_RB_COLORCONTROL);
836 *cmds++ = 0x00000c20;
837
838 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 4);
839 *cmds++ = PM4_REG(REG_VGT_MAX_VTX_INDX);
840 *cmds++ = 0x00ffffff; /* mmVGT_MAX_VTX_INDX */
841 *cmds++ = 0x0; /* mmVGT_MIN_VTX_INDX */
842 *cmds++ = 0x00000000; /* mmVGT_INDX_OFFSET */
843
844 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
845 *cmds++ = PM4_REG(REG_VGT_VERTEX_REUSE_BLOCK_CNTL);
846 *cmds++ = 0x00000002; /* mmVGT_VERTEX_REUSE_BLOCK_CNTL */
847 *cmds++ = 0x00000002; /* mmVGT_OUT_DEALLOC_CNTL */
848
849 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
850 *cmds++ = PM4_REG(REG_SQ_INTERPOLATOR_CNTL);
851 *cmds++ = 0xffffffff; /* mmSQ_INTERPOLATOR_CNTL */
852
853 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
854 *cmds++ = PM4_REG(REG_PA_SC_AA_CONFIG);
855 *cmds++ = 0x00000000; /* REG_PA_SC_AA_CONFIG */
856
857 /* set REG_PA_SU_SC_MODE_CNTL
858 * Front_ptype = draw triangles
859 * Back_ptype = draw triangles
860 * Provoking vertex = last
861 */
862 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
863 *cmds++ = PM4_REG(REG_PA_SU_SC_MODE_CNTL);
864 *cmds++ = 0x00080240;
865
866 /* texture constants */
867 *cmds++ =
868 pm4_type3_packet(PM4_SET_CONSTANT, (SYS2GMEM_TEX_CONST_LEN + 1));
869 *cmds++ = (0x1 << 16) | (0 * 6);
870 memcpy(cmds, sys2gmem_tex_const, SYS2GMEM_TEX_CONST_LEN << 2);
871 cmds[0] |= (shadow->pitch >> 5) << 22;
872 cmds[1] |=
873 shadow->gmemshadow.gpuaddr | surface_format_table[shadow->format];
874 cmds[2] |= (shadow->width - 1) | (shadow->height - 1) << 13;
875 cmds += SYS2GMEM_TEX_CONST_LEN;
876
877 /* program surface info */
878 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
879 *cmds++ = PM4_REG(REG_RB_SURFACE_INFO);
880 *cmds++ = shadow->gmem_pitch; /* pitch, MSAA = 1 */
881
882 /* RB_COLOR_INFO Endian=none, Linear, Format=RGBA8888, Swap=0,
883 * Base=gmem_base
884 */
885 *cmds++ =
886 (shadow->
887 format << RB_COLOR_INFO__COLOR_FORMAT__SHIFT) | tmp_ctx.gmem_base;
888
889 /* RB_DEPTHCONTROL */
890 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
891 *cmds++ = PM4_REG(REG_RB_DEPTHCONTROL);
892
893 if (adreno_is_a220(adreno_dev))
894 *cmds++ = 8; /* disable Z */
895 else
896 *cmds++ = 0; /* disable Z */
897
898 /* Use maximum scissor values -- quad vertices already
899 * have the correct bounds */
900 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
901 *cmds++ = PM4_REG(REG_PA_SC_SCREEN_SCISSOR_TL);
902 *cmds++ = (0 << 16) | 0;
903 *cmds++ = ((0x1fff) << 16) | 0x1fff;
904 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
905 *cmds++ = PM4_REG(REG_PA_SC_WINDOW_SCISSOR_TL);
906 *cmds++ = (unsigned int)((1U << 31) | (0 << 16) | 0);
907 *cmds++ = ((0x1fff) << 16) | 0x1fff;
908
909 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
910 *cmds++ = PM4_REG(REG_PA_CL_VTE_CNTL);
911 /* disable X/Y/Z transforms, X/Y/Z are premultiplied by W */
912 *cmds++ = 0x00000b00;
913
914 /*load the viewport so that z scale = clear depth and z offset = 0.0f */
915 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
916 *cmds++ = PM4_REG(REG_PA_CL_VPORT_ZSCALE);
917 *cmds++ = 0xbf800000;
918 *cmds++ = 0x0;
919
920 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
921 *cmds++ = PM4_REG(REG_RB_COLOR_MASK);
922 *cmds++ = 0x0000000f; /* R = G = B = 1:enabled */
923
924 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
925 *cmds++ = PM4_REG(REG_RB_COLOR_DEST_MASK);
926 *cmds++ = 0xffffffff;
927
928 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 3);
929 *cmds++ = PM4_REG(REG_SQ_WRAPPING_0);
930 *cmds++ = 0x00000000;
931 *cmds++ = 0x00000000;
932
933 /* load the stencil ref value
934 * $AAM - do this later
935 */
936 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
937 *cmds++ = PM4_REG(REG_RB_MODECONTROL);
938 /* draw pixels with color and depth/stencil component */
939 *cmds++ = 0x4;
940
941 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
942 *cmds++ = PM4_REG(REG_PA_CL_CLIP_CNTL);
943 *cmds++ = 0x00010000;
944
945 if (adreno_is_a220(adreno_dev)) {
946 *cmds++ = pm4_type3_packet(PM4_SET_DRAW_INIT_FLAGS, 1);
947 *cmds++ = 0;
948
949 *cmds++ = pm4_type3_packet(PM4_SET_CONSTANT, 2);
950 *cmds++ = PM4_REG(REG_LEIA_RB_LRZ_VSC_CONTROL);
951 *cmds++ = 0x0000000;
952
953 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 3);
954 *cmds++ = 0; /* viz query info. */
955 /* PrimType=RectList, SrcSel=AutoIndex, VisCullMode=Ignore*/
956 *cmds++ = 0x00004088;
957 *cmds++ = 3; /* NumIndices=3 */
958 } else {
959 /* queue the draw packet */
960 *cmds++ = pm4_type3_packet(PM4_DRAW_INDX, 2);
961 *cmds++ = 0; /* viz query info. */
962 /* PrimType=RectList, NumIndices=3, SrcSel=AutoIndex */
963 *cmds++ = 0x00030088;
964 }
965
966 /* create indirect buffer command for above command sequence */
967 create_ib1(drawctxt, shadow->gmem_restore, start, cmds);
968
969 return cmds;
970}
971
972/* restore h/w regs, alu constants, texture constants, etc. ... */
973static unsigned *reg_range(unsigned int *cmd, unsigned int start,
974 unsigned int end)
975{
976 *cmd++ = PM4_REG(start); /* h/w regs, start addr */
977 *cmd++ = end - start + 1; /* count */
978 return cmd;
979}
980
981static void build_regrestore_cmds(struct adreno_device *adreno_dev,
982 struct adreno_context *drawctxt)
983{
984 unsigned int *start = tmp_ctx.cmd;
985 unsigned int *cmd = start;
986
987 unsigned int i = 0;
988 unsigned int reg_array_size = 0;
989 const unsigned int *ptr_register_ranges;
990
991 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
992 *cmd++ = 0;
993
994 /* H/W Registers */
995 /* deferred pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, ???); */
996 cmd++;
997#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
998 /* Force mismatch */
999 *cmd++ = ((drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000) | 1;
1000#else
1001 *cmd++ = (drawctxt->gpustate.gpuaddr + REG_OFFSET) & 0xFFFFE000;
1002#endif
1003
1004 /* Based on chip id choose the registers ranges*/
1005 if (adreno_is_a220(adreno_dev)) {
1006 ptr_register_ranges = register_ranges_a22x;
1007 reg_array_size = ARRAY_SIZE(register_ranges_a22x);
1008 } else {
1009 ptr_register_ranges = register_ranges_a20x;
1010 reg_array_size = ARRAY_SIZE(register_ranges_a20x);
1011 }
1012
1013
1014 for (i = 0; i < (reg_array_size/2); i++) {
1015 cmd = reg_range(cmd, ptr_register_ranges[i*2],
1016 ptr_register_ranges[i*2+1]);
1017 }
1018
1019 /* Now we know how many register blocks we have, we can compute command
1020 * length
1021 */
1022 start[2] =
1023 pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, (cmd - start) - 3);
1024 /* Enable shadowing for the entire register block. */
1025#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1026 start[4] |= (0 << 24) | (4 << 16); /* Disable shadowing. */
1027#else
1028 start[4] |= (1 << 24) | (4 << 16);
1029#endif
1030
1031 /* Need to handle some of the registers separately */
1032 *cmd++ = pm4_type0_packet(REG_SQ_GPR_MANAGEMENT, 1);
1033 tmp_ctx.reg_values[0] = virt2gpu(cmd, &drawctxt->gpustate);
1034 *cmd++ = 0x00040400;
1035
1036 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1037 *cmd++ = 0;
1038 *cmd++ = pm4_type0_packet(REG_TP0_CHICKEN, 1);
1039 tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate);
1040 *cmd++ = 0x00000000;
1041
1042 if (adreno_is_a220(adreno_dev)) {
1043 unsigned int i;
1044 unsigned int j = 2;
1045 for (i = REG_LEIA_VSC_BIN_SIZE; i <=
1046 REG_LEIA_VSC_PIPE_DATA_LENGTH_7; i++) {
1047 *cmd++ = pm4_type0_packet(i, 1);
1048 tmp_ctx.reg_values[j] = virt2gpu(cmd,
1049 &drawctxt->gpustate);
1050 *cmd++ = 0x00000000;
1051 j++;
1052 }
1053 }
1054
1055 /* ALU Constants */
1056 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
1057 *cmd++ = drawctxt->gpustate.gpuaddr & 0xFFFFE000;
1058#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1059 *cmd++ = (0 << 24) | (0 << 16) | 0; /* Disable shadowing */
1060#else
1061 *cmd++ = (1 << 24) | (0 << 16) | 0;
1062#endif
1063 *cmd++ = ALU_CONSTANTS;
1064
1065 /* Texture Constants */
1066 *cmd++ = pm4_type3_packet(PM4_LOAD_CONSTANT_CONTEXT, 3);
1067 *cmd++ = (drawctxt->gpustate.gpuaddr + TEX_OFFSET) & 0xFFFFE000;
1068#ifdef CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES
1069 /* Disable shadowing */
1070 *cmd++ = (0 << 24) | (1 << 16) | 0;
1071#else
1072 *cmd++ = (1 << 24) | (1 << 16) | 0;
1073#endif
1074 *cmd++ = TEX_CONSTANTS;
1075
1076 /* Boolean Constants */
1077 *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + BOOL_CONSTANTS);
1078 *cmd++ = (2 << 16) | 0;
1079
1080 /* the next BOOL_CONSTANT dwords is the shadow area for
1081 * boolean constants.
1082 */
1083 tmp_ctx.bool_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1084 cmd += BOOL_CONSTANTS;
1085
1086 /* Loop Constants */
1087 *cmd++ = pm4_type3_packet(PM4_SET_CONSTANT, 1 + LOOP_CONSTANTS);
1088 *cmd++ = (3 << 16) | 0;
1089
1090 /* the next LOOP_CONSTANTS dwords is the shadow area for
1091 * loop constants.
1092 */
1093 tmp_ctx.loop_shadow = virt2gpu(cmd, &drawctxt->gpustate);
1094 cmd += LOOP_CONSTANTS;
1095
1096 /* create indirect buffer command for above command sequence */
1097 create_ib1(drawctxt, drawctxt->reg_restore, start, cmd);
1098
1099 tmp_ctx.cmd = cmd;
1100}
1101
1102/* quad for saving/restoring gmem */
1103static void set_gmem_copy_quad(struct gmem_shadow_t *shadow)
1104{
1105 /* set vertex buffer values */
1106 gmem_copy_quad[1] = uint2float(shadow->height);
1107 gmem_copy_quad[3] = uint2float(shadow->width);
1108 gmem_copy_quad[4] = uint2float(shadow->height);
1109 gmem_copy_quad[9] = uint2float(shadow->width);
1110
1111 gmem_copy_quad[0] = uint2float(0);
1112 gmem_copy_quad[6] = uint2float(0);
1113 gmem_copy_quad[7] = uint2float(0);
1114 gmem_copy_quad[10] = uint2float(0);
1115
1116 memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
1117
1118 memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
1119 TEXCOORD_LEN << 2);
1120}
1121
1122/* quad for saving/restoring gmem */
1123static void build_quad_vtxbuff(struct adreno_context *drawctxt,
1124 struct gmem_shadow_t *shadow)
1125{
1126 unsigned int *cmd = tmp_ctx.cmd;
1127
1128 /* quad vertex buffer location (in GPU space) */
1129 shadow->quad_vertices.hostptr = cmd;
1130 shadow->quad_vertices.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
1131
1132 cmd += QUAD_LEN;
1133
1134 /* tex coord buffer location (in GPU space) */
1135 shadow->quad_texcoords.hostptr = cmd;
1136 shadow->quad_texcoords.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
1137
1138 cmd += TEXCOORD_LEN;
1139
1140 set_gmem_copy_quad(shadow);
1141
1142 tmp_ctx.cmd = cmd;
1143}
1144
1145static void
1146build_shader_save_restore_cmds(struct adreno_context *drawctxt)
1147{
1148 unsigned int *cmd = tmp_ctx.cmd;
1149 unsigned int *save, *restore, *fixup;
1150#if defined(PM4_IM_STORE)
1151 unsigned int *startSizeVtx, *startSizePix, *startSizeShared;
1152#endif
1153 unsigned int *partition1;
1154 unsigned int *shaderBases, *partition2;
1155
1156#if defined(PM4_IM_STORE)
1157 /* compute vertex, pixel and shared instruction shadow GPU addresses */
1158 tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
1159 tmp_ctx.shader_pixel = tmp_ctx.shader_vertex + SHADER_SHADOW_SIZE;
1160 tmp_ctx.shader_shared = tmp_ctx.shader_pixel + SHADER_SHADOW_SIZE;
1161#endif
1162
1163 /* restore shader partitioning and instructions */
1164
1165 restore = cmd; /* start address */
1166
1167 /* Invalidate Vertex & Pixel instruction code address and sizes */
1168 *cmd++ = pm4_type3_packet(PM4_INVALIDATE_STATE, 1);
1169 *cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
1170
1171 /* Restore previous shader vertex & pixel instruction bases. */
1172 *cmd++ = pm4_type3_packet(PM4_SET_SHADER_BASES, 1);
1173 shaderBases = cmd++; /* TBD #5: shader bases (from fixup) */
1174
1175 /* write the shader partition information to a scratch register */
1176 *cmd++ = pm4_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
1177 partition1 = cmd++; /* TBD #4a: partition info (from save) */
1178
1179#if defined(PM4_IM_STORE)
1180 /* load vertex shader instructions from the shadow. */
1181 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1182 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1183 startSizeVtx = cmd++; /* TBD #1: start/size (from save) */
1184
1185 /* load pixel shader instructions from the shadow. */
1186 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1187 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1188 startSizePix = cmd++; /* TBD #2: start/size (from save) */
1189
1190 /* load shared shader instructions from the shadow. */
1191 *cmd++ = pm4_type3_packet(PM4_IM_LOAD, 2);
1192 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1193 startSizeShared = cmd++; /* TBD #3: start/size (from save) */
1194#endif
1195
1196 /* create indirect buffer command for above command sequence */
1197 create_ib1(drawctxt, drawctxt->shader_restore, restore, cmd);
1198
1199 /*
1200 * fixup SET_SHADER_BASES data
1201 *
1202 * since self-modifying PM4 code is being used here, a seperate
1203 * command buffer is used for this fixup operation, to ensure the
1204 * commands are not read by the PM4 engine before the data fields
1205 * have been written.
1206 */
1207
1208 fixup = cmd; /* start address */
1209
1210 /* write the shader partition information to a scratch register */
1211 *cmd++ = pm4_type0_packet(REG_SCRATCH_REG2, 1);
1212 partition2 = cmd++; /* TBD #4b: partition info (from save) */
1213
1214 /* mask off unused bits, then OR with shader instruction memory size */
1215 *cmd++ = pm4_type3_packet(PM4_REG_RMW, 3);
1216 *cmd++ = REG_SCRATCH_REG2;
1217 /* AND off invalid bits. */
1218 *cmd++ = 0x0FFF0FFF;
1219 /* OR in instruction memory size */
1220 *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2 - 5U) << 29);
1221
1222 /* write the computed value to the SET_SHADER_BASES data field */
1223 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1224 *cmd++ = REG_SCRATCH_REG2;
1225 /* TBD #5: shader bases (to restore) */
1226 *cmd++ = virt2gpu(shaderBases, &drawctxt->gpustate);
1227
1228 /* create indirect buffer command for above command sequence */
1229 create_ib1(drawctxt, drawctxt->shader_fixup, fixup, cmd);
1230
1231 /* save shader partitioning and instructions */
1232
1233 save = cmd; /* start address */
1234
1235 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1236 *cmd++ = 0;
1237
1238 /* fetch the SQ_INST_STORE_MANAGMENT register value,
1239 * store the value in the data fields of the SET_CONSTANT commands
1240 * above.
1241 */
1242 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1243 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1244 /* TBD #4a: partition info (to restore) */
1245 *cmd++ = virt2gpu(partition1, &drawctxt->gpustate);
1246 *cmd++ = pm4_type3_packet(PM4_REG_TO_MEM, 2);
1247 *cmd++ = REG_SQ_INST_STORE_MANAGMENT;
1248 /* TBD #4b: partition info (to fixup) */
1249 *cmd++ = virt2gpu(partition2, &drawctxt->gpustate);
1250
1251#if defined(PM4_IM_STORE)
1252
1253 /* store the vertex shader instructions */
1254 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1255 *cmd++ = tmp_ctx.shader_vertex + 0x0; /* 0x0 = Vertex */
1256 /* TBD #1: start/size (to restore) */
1257 *cmd++ = virt2gpu(startSizeVtx, &drawctxt->gpustate);
1258
1259 /* store the pixel shader instructions */
1260 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1261 *cmd++ = tmp_ctx.shader_pixel + 0x1; /* 0x1 = Pixel */
1262 /* TBD #2: start/size (to restore) */
1263 *cmd++ = virt2gpu(startSizePix, &drawctxt->gpustate);
1264
1265 /* store the shared shader instructions if vertex base is nonzero */
1266
1267 *cmd++ = pm4_type3_packet(PM4_IM_STORE, 2);
1268 *cmd++ = tmp_ctx.shader_shared + 0x2; /* 0x2 = Shared */
1269 /* TBD #3: start/size (to restore) */
1270 *cmd++ = virt2gpu(startSizeShared, &drawctxt->gpustate);
1271
1272#endif
1273
1274 *cmd++ = pm4_type3_packet(PM4_WAIT_FOR_IDLE, 1);
1275 *cmd++ = 0;
1276
1277 /* create indirect buffer command for above command sequence */
1278 create_ib1(drawctxt, drawctxt->shader_save, save, cmd);
1279
1280 tmp_ctx.cmd = cmd;
1281}
1282
1283/* create buffers for saving/restoring registers, constants, & GMEM */
1284static int a2xx_ctxt_gpustate_shadow(struct adreno_device *adreno_dev,
1285 struct adreno_context *drawctxt)
1286{
1287 int result;
1288
1289 /* Allocate vmalloc memory to store the gpustate */
1290 result = kgsl_allocate(&drawctxt->gpustate,
1291 drawctxt->pagetable, CONTEXT_SIZE);
1292
1293 if (result)
1294 return result;
1295
1296 drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
1297
1298 /* Blank out h/w register, constant, and command buffer shadows. */
1299 kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
1300
1301 /* set-up command and vertex buffer pointers */
1302 tmp_ctx.cmd = tmp_ctx.start
1303 = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
1304
1305 /* build indirect command buffers to save & restore regs/constants */
1306 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1307 build_regrestore_cmds(adreno_dev, drawctxt);
1308 build_regsave_cmds(adreno_dev, drawctxt);
1309
1310 build_shader_save_restore_cmds(drawctxt);
1311
1312 kgsl_cache_range_op(&drawctxt->gpustate,
1313 KGSL_CACHE_OP_FLUSH);
1314
1315 return 0;
1316}
1317
1318/* create buffers for saving/restoring registers, constants, & GMEM */
1319static int a2xx_ctxt_gmem_shadow(struct adreno_device *adreno_dev,
1320 struct adreno_context *drawctxt)
1321{
1322 int result;
1323
1324 config_gmemsize(&drawctxt->context_gmem_shadow,
1325 adreno_dev->gmemspace.sizebytes);
1326 tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
1327
1328 result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
1329 drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
1330
1331 if (result)
1332 return result;
1333
1334 /* we've allocated the shadow, when swapped out, GMEM must be saved. */
1335 drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
1336
1337 /* blank out gmem shadow. */
1338 kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
1339 drawctxt->context_gmem_shadow.size);
1340
1341 /* build quad vertex buffer */
1342 build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow);
1343
1344 /* build TP0_CHICKEN register restore command buffer */
1345 tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
1346
1347 /* build indirect command buffers to save & restore gmem */
1348 /* Idle because we are reading PM override registers */
1349 adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT);
1350 drawctxt->context_gmem_shadow.gmem_save_commands = tmp_ctx.cmd;
1351 tmp_ctx.cmd =
1352 build_gmem2sys_cmds(adreno_dev, drawctxt,
1353 &drawctxt->context_gmem_shadow);
1354 drawctxt->context_gmem_shadow.gmem_restore_commands = tmp_ctx.cmd;
1355 tmp_ctx.cmd =
1356 build_sys2gmem_cmds(adreno_dev, drawctxt,
1357 &drawctxt->context_gmem_shadow);
1358
1359 kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
1360 KGSL_CACHE_OP_FLUSH);
1361
1362 return 0;
1363}
1364
1365static void a2xx_ctxt_save(struct adreno_device *adreno_dev,
1366 struct adreno_context *context)
1367{
1368 struct kgsl_device *device = &adreno_dev->dev;
1369
1370 if (context == NULL)
1371 return;
1372
1373 if (context->flags & CTXT_FLAGS_GPU_HANG)
1374 KGSL_CTXT_WARN(device,
1375 "Current active context has caused gpu hang\n");
1376
1377 KGSL_CTXT_INFO(device,
1378 "active context flags %08x\n", context->flags);
1379
1380 /* save registers and constants. */
1381 adreno_ringbuffer_issuecmds(device, 0, context->reg_save, 3);
1382
1383 if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
1384 /* save shader partitioning and instructions. */
1385 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1386 context->shader_save, 3);
1387
1388 /* fixup shader partitioning parameter for
1389 * SET_SHADER_BASES.
1390 */
1391 adreno_ringbuffer_issuecmds(device, 0,
1392 context->shader_fixup, 3);
1393
1394 context->flags |= CTXT_FLAGS_SHADER_RESTORE;
1395 }
1396
1397 if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
1398 (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
1399 /* save gmem.
1400 * (note: changes shader. shader must already be saved.)
1401 */
1402 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1403 context->context_gmem_shadow.gmem_save, 3);
1404
1405 /* Restore TP0_CHICKEN */
1406 adreno_ringbuffer_issuecmds(device, 0,
1407 context->chicken_restore, 3);
1408
1409 context->flags |= CTXT_FLAGS_GMEM_RESTORE;
1410 }
1411}
1412
1413static void a2xx_ctxt_restore(struct adreno_device *adreno_dev,
1414 struct adreno_context *context)
1415{
1416 struct kgsl_device *device = &adreno_dev->dev;
1417 unsigned int cmds[5];
1418
1419 if (context == NULL) {
1420 /* No context - set the default apgetable and thats it */
1421 kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
1422 return;
1423 }
1424
1425 KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
1426
1427 cmds[0] = pm4_nop_packet(1);
1428 cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
1429 cmds[2] = pm4_type3_packet(PM4_MEM_WRITE, 2);
1430 cmds[3] = device->memstore.gpuaddr +
1431 KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
1432 cmds[4] = (unsigned int) context;
1433 adreno_ringbuffer_issuecmds(device, 0, cmds, 5);
1434 kgsl_mmu_setstate(device, context->pagetable);
1435
1436#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
1437 kgsl_cffdump_syncmem(NULL, &context->gpustate,
1438 context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
1439 REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
1440#endif
1441
1442 /* restore gmem.
1443 * (note: changes shader. shader must not already be restored.)
1444 */
1445 if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
1446 adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
1447 context->context_gmem_shadow.gmem_restore, 3);
1448
1449 /* Restore TP0_CHICKEN */
1450 adreno_ringbuffer_issuecmds(device, 0,
1451 context->chicken_restore, 3);
1452
1453 context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
1454 }
1455
1456 /* restore registers and constants. */
1457 adreno_ringbuffer_issuecmds(device, 0,
1458 context->reg_restore, 3);
1459
1460 /* restore shader instructions & partitioning. */
1461 if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
1462 adreno_ringbuffer_issuecmds(device, 0,
1463 context->shader_restore, 3);
1464 }
1465
1466 cmds[0] = pm4_type3_packet(PM4_SET_BIN_BASE_OFFSET, 1);
1467 cmds[1] = context->bin_base_offset;
1468 if (!adreno_is_a220(adreno_dev))
1469 adreno_ringbuffer_issuecmds(device, 0, cmds, 2);
1470}
1471
1472/*
1473 * Interrupt management
1474 *
1475 * a2xx interrupt control is distributed among the various
1476 * hardware components (RB, CP, MMU). The main interrupt
1477 * tells us which component fired the interrupt, but one needs
1478 * to go to the individual component to find out why. The
1479 * following functions provide the broken out support for
1480 * managing the interrupts
1481 */
1482
1483#define KGSL_RBBM_INT_MASK \
1484 (RBBM_INT_CNTL__RDERR_INT_MASK | \
1485 RBBM_INT_CNTL__DISPLAY_UPDATE_INT_MASK)
1486
1487#define KGSL_CP_INT_MASK \
1488 (CP_INT_CNTL__SW_INT_MASK | \
1489 CP_INT_CNTL__T0_PACKET_IN_IB_MASK | \
1490 CP_INT_CNTL__OPCODE_ERROR_MASK | \
1491 CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK | \
1492 CP_INT_CNTL__RESERVED_BIT_ERROR_MASK | \
1493 CP_INT_CNTL__IB_ERROR_MASK | \
1494 CP_INT_CNTL__IB2_INT_MASK | \
1495 CP_INT_CNTL__IB1_INT_MASK | \
1496 CP_INT_CNTL__RB_INT_MASK)
1497
1498#define VALID_STATUS_COUNT_MAX 10
1499
1500static void a2xx_cp_intrcallback(struct kgsl_device *device)
1501{
1502 unsigned int status = 0, num_reads = 0, master_status = 0;
1503 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
1504 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
1505
1506 adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
1507 while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
1508 (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
1509 adreno_regread(device, REG_CP_INT_STATUS, &status);
1510 adreno_regread(device, REG_MASTER_INT_SIGNAL,
1511 &master_status);
1512 num_reads++;
1513 }
1514 if (num_reads > 1)
1515 KGSL_DRV_WARN(device,
1516 "Looped %d times to read REG_CP_INT_STATUS\n",
1517 num_reads);
1518 if (!status) {
1519 if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1520 /* This indicates that we could not read CP_INT_STAT.
1521 * As a precaution just wake up processes so
1522 * they can check their timestamps. Since, we
1523 * did not ack any interrupts this interrupt will
1524 * be generated again */
1525 KGSL_DRV_WARN(device, "Unable to read CP_INT_STATUS\n");
1526 wake_up_interruptible_all(&device->wait_queue);
1527 } else
1528 KGSL_DRV_WARN(device, "Spurious interrput detected\n");
1529 return;
1530 }
1531
1532 if (status & CP_INT_CNTL__RB_INT_MASK) {
1533 /* signal intr completion event */
1534 unsigned int enableflag = 0;
1535 kgsl_sharedmem_writel(&rb->device->memstore,
1536 KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
1537 enableflag);
1538 wmb();
1539 KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
1540 }
1541
1542 if (status & CP_INT_CNTL__T0_PACKET_IN_IB_MASK) {
1543 KGSL_CMD_CRIT(rb->device,
1544 "ringbuffer TO packet in IB interrupt\n");
1545 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1546 }
1547 if (status & CP_INT_CNTL__OPCODE_ERROR_MASK) {
1548 KGSL_CMD_CRIT(rb->device,
1549 "ringbuffer opcode error interrupt\n");
1550 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1551 }
1552 if (status & CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK) {
1553 KGSL_CMD_CRIT(rb->device,
1554 "ringbuffer protected mode error interrupt\n");
1555 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1556 }
1557 if (status & CP_INT_CNTL__RESERVED_BIT_ERROR_MASK) {
1558 KGSL_CMD_CRIT(rb->device,
1559 "ringbuffer reserved bit error interrupt\n");
1560 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1561 }
1562 if (status & CP_INT_CNTL__IB_ERROR_MASK) {
1563 KGSL_CMD_CRIT(rb->device,
1564 "ringbuffer IB error interrupt\n");
1565 kgsl_pwrctrl_irq(rb->device, KGSL_PWRFLAGS_OFF);
1566 }
1567 if (status & CP_INT_CNTL__SW_INT_MASK)
1568 KGSL_CMD_INFO(rb->device, "ringbuffer software interrupt\n");
1569
1570 if (status & CP_INT_CNTL__IB2_INT_MASK)
1571 KGSL_CMD_INFO(rb->device, "ringbuffer ib2 interrupt\n");
1572
1573 if (status & (~KGSL_CP_INT_MASK))
1574 KGSL_CMD_WARN(rb->device,
1575 "bad bits in REG_CP_INT_STATUS %08x\n", status);
1576
1577 /* only ack bits we understand */
1578 status &= KGSL_CP_INT_MASK;
1579 adreno_regwrite(device, REG_CP_INT_ACK, status);
1580
1581 if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
1582 KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
1583 wake_up_interruptible_all(&device->wait_queue);
1584 atomic_notifier_call_chain(&(device->ts_notifier_list),
1585 device->id,
1586 NULL);
1587 }
1588}
1589
1590static void a2xx_rbbm_intrcallback(struct kgsl_device *device)
1591{
1592 unsigned int status = 0;
1593 unsigned int rderr = 0;
1594
1595 adreno_regread(device, REG_RBBM_INT_STATUS, &status);
1596
1597 if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
1598 union rbbm_read_error_u rerr;
1599 adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
1600 rerr.val = rderr;
1601 if (rerr.f.read_address == REG_CP_INT_STATUS &&
1602 rerr.f.read_error &&
1603 rerr.f.read_requester)
1604 KGSL_DRV_WARN(device,
1605 "rbbm read error interrupt: %08x\n", rderr);
1606 else
1607 KGSL_DRV_CRIT(device,
1608 "rbbm read error interrupt: %08x\n", rderr);
1609 } else if (status & RBBM_INT_CNTL__DISPLAY_UPDATE_INT_MASK) {
1610 KGSL_DRV_INFO(device, "rbbm display update interrupt\n");
1611 } else if (status & RBBM_INT_CNTL__GUI_IDLE_INT_MASK) {
1612 KGSL_DRV_INFO(device, "rbbm gui idle interrupt\n");
1613 } else {
1614 KGSL_CMD_WARN(device,
1615 "bad bits in REG_CP_INT_STATUS %08x\n", status);
1616 }
1617
1618 status &= KGSL_RBBM_INT_MASK;
1619 adreno_regwrite(device, REG_RBBM_INT_ACK, status);
1620}
1621
1622irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
1623{
1624 struct kgsl_device *device = &adreno_dev->dev;
1625 irqreturn_t result = IRQ_NONE;
1626 unsigned int status;
1627
1628 adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
1629
1630 if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
1631 kgsl_mh_intrcallback(device);
1632 result = IRQ_HANDLED;
1633 }
1634
1635 if (status & MASTER_INT_SIGNAL__CP_INT_STAT) {
1636 a2xx_cp_intrcallback(device);
1637 result = IRQ_HANDLED;
1638 }
1639
1640 if (status & MASTER_INT_SIGNAL__RBBM_INT_STAT) {
1641 a2xx_rbbm_intrcallback(device);
1642 result = IRQ_HANDLED;
1643 }
1644
1645 return result;
1646}
1647
1648static void a2xx_irq_control(struct adreno_device *adreno_dev, int state)
1649{
1650 struct kgsl_device *device = &adreno_dev->dev;
1651
1652 if (state) {
1653 adreno_regwrite(device, REG_RBBM_INT_CNTL, KGSL_RBBM_INT_MASK);
1654 adreno_regwrite(device, REG_CP_INT_CNTL, KGSL_CP_INT_MASK);
1655 adreno_regwrite(device, MH_INTERRUPT_MASK, KGSL_MMU_INT_MASK);
1656 } else {
1657 adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
1658 adreno_regwrite(device, REG_CP_INT_CNTL, 0);
1659 adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
1660 }
1661}
1662
1663struct adreno_gpudev adreno_a2xx_gpudev = {
1664 .ctxt_gpustate_shadow = a2xx_ctxt_gpustate_shadow,
1665 .ctxt_gmem_shadow = a2xx_ctxt_gmem_shadow,
1666 .ctxt_save = a2xx_ctxt_save,
1667 .ctxt_restore = a2xx_ctxt_restore,
1668 .irq_handler = a2xx_irq_handler,
1669 .irq_control = a2xx_irq_control,
1670};