blob: 9bf85cfa9273b54b2e09e4642ff3313cde7ec27a [file] [log] [blame]
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -07001/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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 */
Jordan Crousea78c9172011-07-11 13:14:09 -060013
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070014#include <linux/slab.h>
15
16#include "kgsl.h"
17#include "kgsl_sharedmem.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#include "adreno.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019
Jordan Crouse0e0486f2011-07-28 08:37:58 -060020/* quad for copying GMEM to context shadow */
21#define QUAD_LEN 12
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070022#define QUAD_RESTORE_LEN 14
Jordan Crouse0e0486f2011-07-28 08:37:58 -060023
24static unsigned int gmem_copy_quad[QUAD_LEN] = {
25 0x00000000, 0x00000000, 0x3f800000,
26 0x00000000, 0x00000000, 0x3f800000,
27 0x00000000, 0x00000000, 0x3f800000,
28 0x00000000, 0x00000000, 0x3f800000
29};
30
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070031static unsigned int gmem_restore_quad[QUAD_RESTORE_LEN] = {
32 0x00000000, 0x3f800000, 0x3f800000,
33 0x00000000, 0x00000000, 0x00000000,
34 0x3f800000, 0x00000000, 0x00000000,
35 0x3f800000, 0x00000000, 0x00000000,
36 0x3f800000, 0x3f800000,
37};
38
Jordan Crouse0e0486f2011-07-28 08:37:58 -060039#define TEXCOORD_LEN 8
40
41static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = {
42 0x00000000, 0x3f800000,
43 0x3f800000, 0x3f800000,
44 0x00000000, 0x00000000,
45 0x3f800000, 0x00000000
46};
47
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048/*
Jordan Crousea78c9172011-07-11 13:14:09 -060049 * Helper functions
50 * These are global helper functions used by the GPUs during context switch
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051 */
52
Jordan Crousea78c9172011-07-11 13:14:09 -060053/**
54 * uint2float - convert a uint to IEEE754 single precision float
55 * @ uintval - value to convert
56 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070057
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070058unsigned int uint2float(unsigned int uintval)
59{
60 unsigned int exp, frac = 0;
61
62 if (uintval == 0)
63 return 0;
64
65 exp = ilog2(uintval);
66
67 /* Calculate fraction */
68 if (23 > exp)
69 frac = (uintval & (~(1 << exp))) << (23 - exp);
70
71 /* Exp is biased by 127 and shifted 23 bits */
72 exp = (exp + 127) << 23;
73
74 return exp | frac;
75}
76
Jordan Crouse0e0486f2011-07-28 08:37:58 -060077static void set_gmem_copy_quad(struct gmem_shadow_t *shadow)
78{
79 /* set vertex buffer values */
80 gmem_copy_quad[1] = uint2float(shadow->height);
81 gmem_copy_quad[3] = uint2float(shadow->width);
82 gmem_copy_quad[4] = uint2float(shadow->height);
83 gmem_copy_quad[9] = uint2float(shadow->width);
84
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070085 gmem_restore_quad[5] = uint2float(shadow->height);
86 gmem_restore_quad[7] = uint2float(shadow->width);
Jordan Crouse0e0486f2011-07-28 08:37:58 -060087
88 memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
Jordan Crouseb4d31bd2012-02-01 22:11:12 -070089 memcpy(shadow->quad_vertices_restore.hostptr, gmem_copy_quad,
90 QUAD_RESTORE_LEN << 2);
Jordan Crouse0e0486f2011-07-28 08:37:58 -060091
92 memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
93 TEXCOORD_LEN << 2);
94}
95
96/**
97 * build_quad_vtxbuff - Create a quad for saving/restoring GMEM
98 * @ context - Pointer to the context being created
99 * @ shadow - Pointer to the GMEM shadow structure
100 * @ incmd - Pointer to pointer to the temporary command buffer
101 */
102
103/* quad for saving/restoring gmem */
104void build_quad_vtxbuff(struct adreno_context *drawctxt,
105 struct gmem_shadow_t *shadow, unsigned int **incmd)
106{
107 unsigned int *cmd = *incmd;
108
109 /* quad vertex buffer location (in GPU space) */
110 shadow->quad_vertices.hostptr = cmd;
111 shadow->quad_vertices.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
112
113 cmd += QUAD_LEN;
114
Jordan Crouseb4d31bd2012-02-01 22:11:12 -0700115 /* Used by A3XX, but define for both to make the code easier */
116 shadow->quad_vertices_restore.hostptr = cmd;
117 shadow->quad_vertices_restore.gpuaddr =
118 virt2gpu(cmd, &drawctxt->gpustate);
119
120 cmd += QUAD_RESTORE_LEN;
121
Jordan Crouse0e0486f2011-07-28 08:37:58 -0600122 /* tex coord buffer location (in GPU space) */
123 shadow->quad_texcoords.hostptr = cmd;
124 shadow->quad_texcoords.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
125
126 cmd += TEXCOORD_LEN;
127
128 set_gmem_copy_quad(shadow);
129 *incmd = cmd;
130}
131
Jordan Crousea78c9172011-07-11 13:14:09 -0600132/**
133 * adreno_drawctxt_create - create a new adreno draw context
134 * @device - KGSL device to create the context on
135 * @pagetable - Pagetable for the context
136 * @context- Generic KGSL context structure
137 * @flags - flags for the context (passed from user space)
138 *
139 * Create a new draw context for the 3D core. Return 0 on success,
140 * or error code on failure.
141 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142int adreno_drawctxt_create(struct kgsl_device *device,
143 struct kgsl_pagetable *pagetable,
144 struct kgsl_context *context, uint32_t flags)
145{
146 struct adreno_context *drawctxt;
147 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 int ret;
149
150 drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
151
152 if (drawctxt == NULL)
153 return -ENOMEM;
154
155 drawctxt->pagetable = pagetable;
156 drawctxt->bin_base_offset = 0;
157
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700158 if (flags & KGSL_CONTEXT_PREAMBLE)
159 drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
Jordan Crousea78c9172011-07-11 13:14:09 -0600160
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700161 if (flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
162 drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
163
164 ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 if (ret)
166 goto err;
167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168 context->devctxt = drawctxt;
169 return 0;
170err:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700171 kfree(drawctxt);
172 return ret;
173}
174
Jordan Crousea78c9172011-07-11 13:14:09 -0600175/**
176 * adreno_drawctxt_destroy - destroy a draw context
177 * @device - KGSL device that owns the context
178 * @context- Generic KGSL context container for the context
179 *
180 * Destroy an existing context. Return 0 on success or error
181 * code on failure.
182 */
183
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700184/* destroy a drawing context */
185
186void adreno_drawctxt_destroy(struct kgsl_device *device,
187 struct kgsl_context *context)
188{
189 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
190 struct adreno_context *drawctxt = context->devctxt;
191
192 if (drawctxt == NULL)
193 return;
194
195 /* deactivate context */
196 if (adreno_dev->drawctxt_active == drawctxt) {
197 /* no need to save GMEM or shader, the context is
198 * being destroyed.
199 */
200 drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE |
201 CTXT_FLAGS_SHADER_SAVE |
202 CTXT_FLAGS_GMEM_SHADOW |
203 CTXT_FLAGS_STATE_SHADOW);
204
205 adreno_drawctxt_switch(adreno_dev, NULL, 0);
206 }
207
208 adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
209
210 kgsl_sharedmem_free(&drawctxt->gpustate);
211 kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
212
213 kfree(drawctxt);
214 context->devctxt = NULL;
215}
216
Jordan Crousea78c9172011-07-11 13:14:09 -0600217/**
218 * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context
219 * @device - KGSL device that owns the context
220 * @context- Generic KGSL context container for the context
221 * @offset - Offset to set
222 *
223 * Set the bin base offset for A2XX devices. Not valid for A3XX devices.
224 */
225
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226void adreno_drawctxt_set_bin_base_offset(struct kgsl_device *device,
227 struct kgsl_context *context,
228 unsigned int offset)
229{
230 struct adreno_context *drawctxt = context->devctxt;
231
232 if (drawctxt)
233 drawctxt->bin_base_offset = offset;
234}
235
Jordan Crousea78c9172011-07-11 13:14:09 -0600236/**
237 * adreno_drawctxt_switch - switch the current draw context
238 * @adreno_dev - The 3D device that owns the context
239 * @drawctxt - the 3D context to switch to
240 * @flags - Flags to accompany the switch (from user space)
241 *
242 * Switch the current draw context
243 */
244
245void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
246 struct adreno_context *drawctxt,
247 unsigned int flags)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700248{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700249 struct kgsl_device *device = &adreno_dev->dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700250
251 if (drawctxt) {
252 if (flags & KGSL_CONTEXT_SAVE_GMEM)
253 /* Set the flag in context so that the save is done
254 * when this context is switched out. */
255 drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE;
256 else
257 /* Remove GMEM saving flag from the context */
258 drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE;
259 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600260
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 /* already current? */
Jordan Crousea78c9172011-07-11 13:14:09 -0600262 if (adreno_dev->drawctxt_active == drawctxt)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 return;
264
265 KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
266 adreno_dev->drawctxt_active, drawctxt, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267
Jordan Crousea78c9172011-07-11 13:14:09 -0600268 /* Save the old context */
269 adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270
Jordan Crousea78c9172011-07-11 13:14:09 -0600271 /* Set the new context */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 adreno_dev->drawctxt_active = drawctxt;
Jordan Crousea78c9172011-07-11 13:14:09 -0600273 adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274}