blob: 3349e352636071670eaa8f38e2903dd2f0e15d77 [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 */
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
20/*
Jordan Crousea78c9172011-07-11 13:14:09 -060021 * Helper functions
22 * These are global helper functions used by the GPUs during context switch
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023 */
24
Jordan Crousea78c9172011-07-11 13:14:09 -060025/**
26 * uint2float - convert a uint to IEEE754 single precision float
27 * @ uintval - value to convert
28 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030unsigned int uint2float(unsigned int uintval)
31{
32 unsigned int exp, frac = 0;
33
34 if (uintval == 0)
35 return 0;
36
37 exp = ilog2(uintval);
38
39 /* Calculate fraction */
40 if (23 > exp)
41 frac = (uintval & (~(1 << exp))) << (23 - exp);
42
43 /* Exp is biased by 127 and shifted 23 bits */
44 exp = (exp + 127) << 23;
45
46 return exp | frac;
47}
48
Jordan Crousea78c9172011-07-11 13:14:09 -060049/**
50 * adreno_drawctxt_create - create a new adreno draw context
51 * @device - KGSL device to create the context on
52 * @pagetable - Pagetable for the context
53 * @context- Generic KGSL context structure
54 * @flags - flags for the context (passed from user space)
55 *
56 * Create a new draw context for the 3D core. Return 0 on success,
57 * or error code on failure.
58 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059int adreno_drawctxt_create(struct kgsl_device *device,
60 struct kgsl_pagetable *pagetable,
61 struct kgsl_context *context, uint32_t flags)
62{
63 struct adreno_context *drawctxt;
64 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065 int ret;
66
67 drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
68
69 if (drawctxt == NULL)
70 return -ENOMEM;
71
72 drawctxt->pagetable = pagetable;
73 drawctxt->bin_base_offset = 0;
74
Jordan Crousea78c9172011-07-11 13:14:09 -060075 /* FIXME: Deal with preambles */
76
77 ret = adreno_dev->gpudev->ctxt_gpustate_shadow(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078 if (ret)
79 goto err;
80
81 /* Save the shader instruction memory on context switching */
82 drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
83
84 if (!(flags & KGSL_CONTEXT_NO_GMEM_ALLOC)) {
85 /* create gmem shadow */
Jordan Crousea78c9172011-07-11 13:14:09 -060086 ret = adreno_dev->gpudev->ctxt_gmem_shadow(adreno_dev,
87 drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070088 if (ret != 0)
89 goto err;
90 }
91
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 context->devctxt = drawctxt;
93 return 0;
94err:
95 kgsl_sharedmem_free(&drawctxt->gpustate);
96 kfree(drawctxt);
97 return ret;
98}
99
Jordan Crousea78c9172011-07-11 13:14:09 -0600100/**
101 * adreno_drawctxt_destroy - destroy a draw context
102 * @device - KGSL device that owns the context
103 * @context- Generic KGSL context container for the context
104 *
105 * Destroy an existing context. Return 0 on success or error
106 * code on failure.
107 */
108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109/* destroy a drawing context */
110
111void adreno_drawctxt_destroy(struct kgsl_device *device,
112 struct kgsl_context *context)
113{
114 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
115 struct adreno_context *drawctxt = context->devctxt;
116
117 if (drawctxt == NULL)
118 return;
119
120 /* deactivate context */
121 if (adreno_dev->drawctxt_active == drawctxt) {
122 /* no need to save GMEM or shader, the context is
123 * being destroyed.
124 */
125 drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE |
126 CTXT_FLAGS_SHADER_SAVE |
127 CTXT_FLAGS_GMEM_SHADOW |
128 CTXT_FLAGS_STATE_SHADOW);
129
130 adreno_drawctxt_switch(adreno_dev, NULL, 0);
131 }
132
133 adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
134
135 kgsl_sharedmem_free(&drawctxt->gpustate);
136 kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
137
138 kfree(drawctxt);
139 context->devctxt = NULL;
140}
141
Jordan Crousea78c9172011-07-11 13:14:09 -0600142/**
143 * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context
144 * @device - KGSL device that owns the context
145 * @context- Generic KGSL context container for the context
146 * @offset - Offset to set
147 *
148 * Set the bin base offset for A2XX devices. Not valid for A3XX devices.
149 */
150
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151void adreno_drawctxt_set_bin_base_offset(struct kgsl_device *device,
152 struct kgsl_context *context,
153 unsigned int offset)
154{
155 struct adreno_context *drawctxt = context->devctxt;
156
157 if (drawctxt)
158 drawctxt->bin_base_offset = offset;
159}
160
Jordan Crousea78c9172011-07-11 13:14:09 -0600161/**
162 * adreno_drawctxt_switch - switch the current draw context
163 * @adreno_dev - The 3D device that owns the context
164 * @drawctxt - the 3D context to switch to
165 * @flags - Flags to accompany the switch (from user space)
166 *
167 * Switch the current draw context
168 */
169
170void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
171 struct adreno_context *drawctxt,
172 unsigned int flags)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174 struct kgsl_device *device = &adreno_dev->dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175
176 if (drawctxt) {
177 if (flags & KGSL_CONTEXT_SAVE_GMEM)
178 /* Set the flag in context so that the save is done
179 * when this context is switched out. */
180 drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE;
181 else
182 /* Remove GMEM saving flag from the context */
183 drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE;
184 }
Jordan Crousea78c9172011-07-11 13:14:09 -0600185
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186 /* already current? */
Jordan Crousea78c9172011-07-11 13:14:09 -0600187 if (adreno_dev->drawctxt_active == drawctxt)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700188 return;
189
190 KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
191 adreno_dev->drawctxt_active, drawctxt, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700192
Jordan Crousea78c9172011-07-11 13:14:09 -0600193 /* Save the old context */
194 adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195
Jordan Crousea78c9172011-07-11 13:14:09 -0600196 /* Set the new context */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197 adreno_dev->drawctxt_active = drawctxt;
Jordan Crousea78c9172011-07-11 13:14:09 -0600198 adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199}