blob: 206a678eed87762d0698273dd841e5bb1ae900d6 [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
22
23static unsigned int gmem_copy_quad[QUAD_LEN] = {
24 0x00000000, 0x00000000, 0x3f800000,
25 0x00000000, 0x00000000, 0x3f800000,
26 0x00000000, 0x00000000, 0x3f800000,
27 0x00000000, 0x00000000, 0x3f800000
28};
29
30#define TEXCOORD_LEN 8
31
32static unsigned int gmem_copy_texcoord[TEXCOORD_LEN] = {
33 0x00000000, 0x3f800000,
34 0x3f800000, 0x3f800000,
35 0x00000000, 0x00000000,
36 0x3f800000, 0x00000000
37};
38
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039/*
Jordan Crousea78c9172011-07-11 13:14:09 -060040 * Helper functions
41 * These are global helper functions used by the GPUs during context switch
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042 */
43
Jordan Crousea78c9172011-07-11 13:14:09 -060044/**
45 * uint2float - convert a uint to IEEE754 single precision float
46 * @ uintval - value to convert
47 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049unsigned int uint2float(unsigned int uintval)
50{
51 unsigned int exp, frac = 0;
52
53 if (uintval == 0)
54 return 0;
55
56 exp = ilog2(uintval);
57
58 /* Calculate fraction */
59 if (23 > exp)
60 frac = (uintval & (~(1 << exp))) << (23 - exp);
61
62 /* Exp is biased by 127 and shifted 23 bits */
63 exp = (exp + 127) << 23;
64
65 return exp | frac;
66}
67
Jordan Crouse0e0486f2011-07-28 08:37:58 -060068static void set_gmem_copy_quad(struct gmem_shadow_t *shadow)
69{
70 /* set vertex buffer values */
71 gmem_copy_quad[1] = uint2float(shadow->height);
72 gmem_copy_quad[3] = uint2float(shadow->width);
73 gmem_copy_quad[4] = uint2float(shadow->height);
74 gmem_copy_quad[9] = uint2float(shadow->width);
75
76 gmem_copy_quad[0] = 0;
77 gmem_copy_quad[6] = 0;
78 gmem_copy_quad[7] = 0;
79 gmem_copy_quad[10] = 0;
80
81 memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
82
83 memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
84 TEXCOORD_LEN << 2);
85}
86
87/**
88 * build_quad_vtxbuff - Create a quad for saving/restoring GMEM
89 * @ context - Pointer to the context being created
90 * @ shadow - Pointer to the GMEM shadow structure
91 * @ incmd - Pointer to pointer to the temporary command buffer
92 */
93
94/* quad for saving/restoring gmem */
95void build_quad_vtxbuff(struct adreno_context *drawctxt,
96 struct gmem_shadow_t *shadow, unsigned int **incmd)
97{
98 unsigned int *cmd = *incmd;
99
100 /* quad vertex buffer location (in GPU space) */
101 shadow->quad_vertices.hostptr = cmd;
102 shadow->quad_vertices.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
103
104 cmd += QUAD_LEN;
105
106 /* tex coord buffer location (in GPU space) */
107 shadow->quad_texcoords.hostptr = cmd;
108 shadow->quad_texcoords.gpuaddr = virt2gpu(cmd, &drawctxt->gpustate);
109
110 cmd += TEXCOORD_LEN;
111
112 set_gmem_copy_quad(shadow);
113 *incmd = cmd;
114}
115
Jordan Crousea78c9172011-07-11 13:14:09 -0600116/**
117 * adreno_drawctxt_create - create a new adreno draw context
118 * @device - KGSL device to create the context on
119 * @pagetable - Pagetable for the context
120 * @context- Generic KGSL context structure
121 * @flags - flags for the context (passed from user space)
122 *
123 * Create a new draw context for the 3D core. Return 0 on success,
124 * or error code on failure.
125 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126int adreno_drawctxt_create(struct kgsl_device *device,
127 struct kgsl_pagetable *pagetable,
128 struct kgsl_context *context, uint32_t flags)
129{
130 struct adreno_context *drawctxt;
131 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700132 int ret;
133
134 drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
135
136 if (drawctxt == NULL)
137 return -ENOMEM;
138
139 drawctxt->pagetable = pagetable;
140 drawctxt->bin_base_offset = 0;
141
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700142 if (flags & KGSL_CONTEXT_PREAMBLE)
143 drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
Jordan Crousea78c9172011-07-11 13:14:09 -0600144
Vijay Krishnamoorthybef66932012-01-24 09:32:05 -0700145 if (flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
146 drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
147
148 ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700149 if (ret)
150 goto err;
151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152 context->devctxt = drawctxt;
153 return 0;
154err:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155 kfree(drawctxt);
156 return ret;
157}
158
Jordan Crousea78c9172011-07-11 13:14:09 -0600159/**
160 * adreno_drawctxt_destroy - destroy a draw context
161 * @device - KGSL device that owns the context
162 * @context- Generic KGSL context container for the context
163 *
164 * Destroy an existing context. Return 0 on success or error
165 * code on failure.
166 */
167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168/* destroy a drawing context */
169
170void adreno_drawctxt_destroy(struct kgsl_device *device,
171 struct kgsl_context *context)
172{
173 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
174 struct adreno_context *drawctxt = context->devctxt;
175
176 if (drawctxt == NULL)
177 return;
178
179 /* deactivate context */
180 if (adreno_dev->drawctxt_active == drawctxt) {
181 /* no need to save GMEM or shader, the context is
182 * being destroyed.
183 */
184 drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE |
185 CTXT_FLAGS_SHADER_SAVE |
186 CTXT_FLAGS_GMEM_SHADOW |
187 CTXT_FLAGS_STATE_SHADOW);
188
189 adreno_drawctxt_switch(adreno_dev, NULL, 0);
190 }
191
192 adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
193
194 kgsl_sharedmem_free(&drawctxt->gpustate);
195 kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
196
197 kfree(drawctxt);
198 context->devctxt = NULL;
199}
200
Jordan Crousea78c9172011-07-11 13:14:09 -0600201/**
202 * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context
203 * @device - KGSL device that owns the context
204 * @context- Generic KGSL context container for the context
205 * @offset - Offset to set
206 *
207 * Set the bin base offset for A2XX devices. Not valid for A3XX devices.
208 */
209
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700210void adreno_drawctxt_set_bin_base_offset(struct kgsl_device *device,
211 struct kgsl_context *context,
212 unsigned int offset)
213{
214 struct adreno_context *drawctxt = context->devctxt;
215
216 if (drawctxt)
217 drawctxt->bin_base_offset = offset;
218}
219
Jordan Crousea78c9172011-07-11 13:14:09 -0600220/**
221 * adreno_drawctxt_switch - switch the current draw context
222 * @adreno_dev - The 3D device that owns the context
223 * @drawctxt - the 3D context to switch to
224 * @flags - Flags to accompany the switch (from user space)
225 *
226 * Switch the current draw context
227 */
228
229void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
230 struct adreno_context *drawctxt,
231 unsigned int flags)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233 struct kgsl_device *device = &adreno_dev->dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234
235 if (drawctxt) {
236 if (flags & KGSL_CONTEXT_SAVE_GMEM)
237 /* Set the flag in context so that the save is done
238 * when this context is switched out. */
239 drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE;
240 else
241 /* Remove GMEM saving flag from the context */
242 drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE;
243 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600244
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245 /* already current? */
Jordan Crousea78c9172011-07-11 13:14:09 -0600246 if (adreno_dev->drawctxt_active == drawctxt)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700247 return;
248
249 KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
250 adreno_dev->drawctxt_active, drawctxt, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251
Jordan Crousea78c9172011-07-11 13:14:09 -0600252 /* Save the old context */
253 adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254
Jordan Crousea78c9172011-07-11 13:14:09 -0600255 /* Set the new context */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256 adreno_dev->drawctxt_active = drawctxt;
Jordan Crousea78c9172011-07-11 13:14:09 -0600257 adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258}