msm: kgsl: handle larger instruction store for adreno225
This GPU has a larger instruction store, so more memory
needs to be reserved for saving shader state when context
switching.
The initial vertex and pixel partitioning of the
instruction store also needs to be different.
Change-Id: If60c06467dd30d5bae07302a74eaf2687900b2b8
Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 7599894..b13190d 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -129,21 +129,28 @@
const char *pm4fw;
const char *pfpfw;
struct adreno_gpudev *gpudev;
+ unsigned int istore_size;
+ unsigned int pix_shader_start;
} adreno_gpulist[] = {
{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
- "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev },
+ "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
+ 512, 384},
{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
- "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev },
+ "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
+ 512, 384},
{ ADRENO_REV_A220, 2, 1, ANY_ID, ANY_ID,
- "leia_pm4_470.fw", "leia_pfp_470.fw", &adreno_a2xx_gpudev },
+ "leia_pm4_470.fw", "leia_pfp_470.fw", &adreno_a2xx_gpudev,
+ 512, 384},
/*
* patchlevel 5 (8960v2) needs special pm4 firmware to work around
* a hardware problem.
*/
{ ADRENO_REV_A225, 2, 2, 0, 5,
- "a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev },
+ "a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
+ 1536, 768 },
{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
- "a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev },
+ "a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
+ 1536, 768 },
};
static void adreno_gmeminit(struct adreno_device *adreno_dev)
@@ -413,6 +420,8 @@
adreno_dev->gpudev = adreno_gpulist[i].gpudev;
adreno_dev->pfp_fwfile = adreno_gpulist[i].pfpfw;
adreno_dev->pm4_fwfile = adreno_gpulist[i].pm4fw;
+ adreno_dev->istore_size = adreno_gpulist[i].istore_size;
+ adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start;
}
static int __devinit
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 51ee31a..0776a24 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -38,6 +38,12 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
+/*
+ * constants for the size of shader instructions
+ */
+#define ADRENO_ISTORE_BYTES 12
+#define ADRENO_ISTORE_WORDS 3
+
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
ADRENO_REV_A200 = 200,
@@ -64,6 +70,8 @@
unsigned int mharb;
struct adreno_gpudev *gpudev;
unsigned int wait_timeout;
+ unsigned int istore_size;
+ unsigned int pix_shader_start;
};
struct adreno_gpudev {
@@ -125,5 +133,28 @@
return (adreno_dev->gpurev <= ADRENO_REV_A225);
}
+/**
+ * adreno_encode_istore_size - encode istore size in CP format
+ * @adreno_dev - The 3D device.
+ *
+ * Encode the istore size into the format expected that the
+ * CP_SET_SHADER_BASES and CP_ME_INIT commands:
+ * bits 31:29 - istore size as encoded by this function
+ * bits 27:16 - vertex shader start offset in instructions
+ * bits 11:0 - pixel shader start offset in instructions.
+ */
+static inline int adreno_encode_istore_size(struct adreno_device *adreno_dev)
+{
+ unsigned int size;
+ /* in a225 the CP microcode multiplies the encoded
+ * value by 3 while decoding.
+ */
+ if (adreno_is_a225(adreno_dev))
+ size = adreno_dev->istore_size/3;
+ else
+ size = adreno_dev->istore_size;
+
+ return (ilog2(size) - 5) << 29;
+}
#endif /*__ADRENO_H */
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 064b05e..6003846 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -72,10 +72,6 @@
#define TEX_CONSTANTS (32*6) /* DWORDS */
#define BOOL_CONSTANTS 8 /* DWORDS */
#define LOOP_CONSTANTS 56 /* DWORDS */
-#define SHADER_INSTRUCT_LOG2 9U /* 2^n == SHADER_INSTRUCTIONS */
-
-/* 96-bit instructions */
-#define SHADER_INSTRUCT (1<<SHADER_INSTRUCT_LOG2)
/* LOAD_CONSTANT_CONTEXT shadow size */
#define LCC_SHADOW_SIZE 0x2000 /* 8KB */
@@ -88,14 +84,21 @@
#define CMD_BUFFER_SIZE 0x3000 /* 12KB */
#endif
#define TEX_SHADOW_SIZE (TEX_CONSTANTS*4) /* 768 bytes */
-#define SHADER_SHADOW_SIZE (SHADER_INSTRUCT*12) /* 6KB */
#define REG_OFFSET LCC_SHADOW_SIZE
#define CMD_OFFSET (REG_OFFSET + REG_SHADOW_SIZE)
#define TEX_OFFSET (CMD_OFFSET + CMD_BUFFER_SIZE)
#define SHADER_OFFSET ((TEX_OFFSET + TEX_SHADOW_SIZE + 32) & ~31)
-#define CONTEXT_SIZE (SHADER_OFFSET + 3 * SHADER_SHADOW_SIZE)
+static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
+{
+ return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
+}
+
+static inline int _context_size(struct adreno_device *adreno_dev)
+{
+ return SHADER_OFFSET + 3*_shader_shadow_size(adreno_dev);
+}
/* A scratchpad used to build commands during context create */
@@ -601,7 +604,8 @@
*cmds++ = 0x00003F00;
*cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
- *cmds++ = (0x80000000) | 0x180;
+ *cmds++ = adreno_encode_istore_size(adreno_dev)
+ | adreno_dev->pix_shader_start;
/* load the patched vertex shader stream */
cmds = program_shader(cmds, 0, gmem2sys_vtx_pgm, GMEM2SYS_VTX_PGM_LEN);
@@ -802,7 +806,8 @@
*cmds++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
*cmds++ = cp_type3_packet(CP_SET_SHADER_BASES, 1);
- *cmds++ = (0x80000000) | 0x180;
+ *cmds++ = adreno_encode_istore_size(adreno_dev)
+ | adreno_dev->pix_shader_start;
/* Load the patched fragment shader stream */
cmds =
@@ -1089,7 +1094,8 @@
}
static void
-build_shader_save_restore_cmds(struct adreno_context *drawctxt)
+build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
+ struct adreno_context *drawctxt)
{
unsigned int *cmd = tmp_ctx.cmd;
unsigned int *save, *restore, *fixup;
@@ -1099,8 +1105,10 @@
/* compute vertex, pixel and shared instruction shadow GPU addresses */
tmp_ctx.shader_vertex = drawctxt->gpustate.gpuaddr + SHADER_OFFSET;
- tmp_ctx.shader_pixel = tmp_ctx.shader_vertex + SHADER_SHADOW_SIZE;
- tmp_ctx.shader_shared = tmp_ctx.shader_pixel + SHADER_SHADOW_SIZE;
+ tmp_ctx.shader_pixel = tmp_ctx.shader_vertex
+ + _shader_shadow_size(adreno_dev);
+ tmp_ctx.shader_shared = tmp_ctx.shader_pixel
+ + _shader_shadow_size(adreno_dev);
/* restore shader partitioning and instructions */
@@ -1156,8 +1164,8 @@
*cmd++ = REG_SCRATCH_REG2;
/* AND off invalid bits. */
*cmd++ = 0x0FFF0FFF;
- /* OR in instruction memory size */
- *cmd++ = (unsigned int)((SHADER_INSTRUCT_LOG2 - 5U) << 29);
+ /* OR in instruction memory size. */
+ *cmd++ = adreno_encode_istore_size(adreno_dev);
/* write the computed value to the SET_SHADER_BASES data field */
*cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2);
@@ -1226,7 +1234,7 @@
/* Allocate vmalloc memory to store the gpustate */
result = kgsl_allocate(&drawctxt->gpustate,
- drawctxt->pagetable, CONTEXT_SIZE);
+ drawctxt->pagetable, _context_size(adreno_dev));
if (result)
return result;
@@ -1234,7 +1242,8 @@
drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
/* Blank out h/w register, constant, and command buffer shadows. */
- kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
+ kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
+ _context_size(adreno_dev));
/* set-up command and vertex buffer pointers */
tmp_ctx.cmd = tmp_ctx.start
@@ -1245,7 +1254,7 @@
build_regrestore_cmds(adreno_dev, drawctxt);
build_regsave_cmds(adreno_dev, drawctxt);
- build_shader_save_restore_cmds(drawctxt);
+ build_shader_save_restore_cmds(adreno_dev, drawctxt);
kgsl_cache_range_op(&drawctxt->gpustate,
KGSL_CACHE_OP_FLUSH);
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index c878a2c..419ce9d 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -223,21 +223,23 @@
return 0;
}
-#define KGSL_ISTORE_START 0x5000
-#define KGSL_ISTORE_LENGTH 0x600
+#define ADRENO_ISTORE_START 0x5000
static ssize_t kgsl_istore_read(
struct file *file,
char __user *buff,
size_t buff_count,
loff_t *ppos)
{
- int i, count = KGSL_ISTORE_LENGTH, remaining, pos = 0, tot = 0;
+ int i, count, remaining, pos = 0, tot = 0;
struct kgsl_device *device = file->private_data;
const int rowc = 8;
+ struct adreno_device *adreno_dev;
if (!ppos || !device)
return 0;
+ adreno_dev = ADRENO_DEVICE(device);
+ count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
remaining = count;
for (i = 0; i < count; i += rowc) {
unsigned int vals[rowc];
@@ -248,7 +250,8 @@
if (pos >= *ppos) {
for (j = 0; j < linec; ++j)
kgsl_regread_nolock(device,
- KGSL_ISTORE_START+i+j, vals+j);
+ ADRENO_ISTORE_START + i + j,
+ vals + j);
} else
memset(vals, 0, sizeof(vals));
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index d59057c..a098200 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -246,6 +246,7 @@
union reg_cp_rb_cntl cp_rb_cntl;
unsigned int *cmds, rb_cntl;
struct kgsl_device *device = rb->device;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
uint cmds_gpu;
if (rb->flags & KGSL_FLAGS_STARTED)
@@ -357,9 +358,10 @@
GSL_RB_WRITE(cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
- /* Vertex and Pixel Shader Start Addresses in instructions
- * (3 DWORDS per instruction) */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x80000180);
+ /* Instruction memory size: */
+ GSL_RB_WRITE(cmds, cmds_gpu,
+ (adreno_encode_istore_size(adreno_dev)
+ | adreno_dev->pix_shader_start));
/* Maximum Contexts */
GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
/* Write Confirm Interval and The CP will wait the