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