1 /*
2 * gcmain.c
3 *
4 * Copyright (C) 2010-2011 Vivante Corporation.
5 *
6 * This package is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 */
15 #include "gcbv.h"
16 #include <plat/cpu.h>
17 #include <plat/omap_hwmod.h>
20 /*******************************************************************************
21 * BLTsville interface exposure.
22 */
24 static struct bventry ops = {
25 .structsize = sizeof(struct bventry),
26 };
28 static void gcbv_clear(void)
29 {
30 ops.bv_map = NULL;
31 ops.bv_unmap = NULL;
32 ops.bv_blt = NULL;
33 ops.bv_cache = NULL;
34 }
36 static void gcbv_assign(void)
37 {
38 ops.bv_map = bv_map;
39 ops.bv_unmap = bv_unmap;
40 ops.bv_blt = bv_blt;
41 ops.bv_cache = bv_cache;
42 }
44 void gcbv_init(struct bventry *entry)
45 {
46 *entry = ops;
47 }
48 EXPORT_SYMBOL(gcbv_init);
51 /*******************************************************************************
52 * Convert floating point in 0..1 range to an 8-bit value in range 0..255.
53 */
55 union gcfp {
56 struct {
57 unsigned int mantissa:23;
58 unsigned int exponent:8;
59 unsigned int sign:1;
60 } comp;
62 float value;
63 };
65 unsigned char gcfp2norm8(float value)
66 {
67 union gcfp gcfp;
68 int exponent;
69 unsigned int mantissa;
70 int shift;
72 /* Get access to components. */
73 gcfp.value = value;
75 /* Clamp negatives. */
76 if (gcfp.comp.sign)
77 return 0;
79 /* Get unbiased exponent. */
80 exponent = (int) gcfp.comp.exponent - 127;
82 /* Clamp if too large. */
83 if (exponent >= 0)
84 return 255;
86 /* Clamp if too small. */
87 if (exponent < -8)
88 return 0;
90 /* Determine the shift value. */
91 shift = (23 - 8) - exponent;
93 /* Compute the mantissa. */
94 mantissa = (gcfp.comp.mantissa | 0x00800000) >> shift;
96 /* Normalize. */
97 mantissa = (mantissa * 255) >> 8;
99 return (unsigned char) mantissa;
100 }
103 /*******************************************************************************
104 * Surface allocation.
105 */
107 enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
108 void **buffer,
109 unsigned int size)
110 {
111 enum bverror bverror;
112 struct bvbuffdesc *tempbuffdesc = NULL;
113 void *tempbuff = NULL;
114 unsigned long *temparray = NULL;
115 struct bvphysdesc *tempphysdesc = NULL;
116 unsigned char *pageaddr;
117 unsigned int i;
119 /* Allocate surface buffer descriptor. */
120 tempbuffdesc = vmalloc(sizeof(struct bvbuffdesc));
121 if (tempbuffdesc == NULL) {
122 BVSETERROR(BVERR_OOM, "failed to allocate surface");
123 goto exit;
124 }
126 /* Initialize buffer descriptor. */
127 tempbuffdesc->structsize = sizeof(struct bvbuffdesc);
128 tempbuffdesc->virtaddr = NULL;
129 tempbuffdesc->length = size;
130 tempbuffdesc->map = NULL;
131 tempbuffdesc->auxtype = BVAT_PHYSDESC;
132 tempbuffdesc->auxptr = NULL;
134 /* Allocate the surface. */
135 tempbuff = vmalloc(size);
136 if (tempbuff == NULL) {
137 BVSETERROR(BVERR_OOM, "failed to allocate surface");
138 goto exit;
139 }
140 tempbuffdesc->virtaddr = tempbuff;
142 /* Allocate the physical descriptor. */
143 tempphysdesc = vmalloc(sizeof(struct bvphysdesc));
144 if (tempphysdesc == NULL) {
145 BVSETERROR(BVERR_OOM, "failed to allocate surface");
146 goto exit;
147 }
148 tempbuffdesc->auxptr = tempphysdesc;
150 /* Initialize physical descriptor. */
151 tempphysdesc->structsize = sizeof(struct bvphysdesc);
152 tempphysdesc->pagesize = PAGE_SIZE;
153 tempphysdesc->pagearray = NULL;
154 tempphysdesc->pagecount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
155 tempphysdesc->pageoffset = 0;
157 /* Allocate array of pages. */
158 temparray = vmalloc(tempphysdesc->pagecount * sizeof(unsigned long));
159 if (temparray == NULL) {
160 BVSETERROR(BVERR_OOM, "failed to allocate surface");
161 goto exit;
162 }
163 tempphysdesc->pagearray = temparray;
165 /* Initialize the array. */
166 pageaddr = (unsigned char *) tempbuff;
167 for (i = 0; i < tempphysdesc->pagecount; i += 1) {
168 temparray[i] = PFN_PHYS(vmalloc_to_pfn(pageaddr));
169 pageaddr += PAGE_SIZE;
170 }
172 /* Set return pointers. */
173 *bvbuffdesc = tempbuffdesc;
174 *buffer = tempbuff;
175 return BVERR_NONE;
177 exit:
178 free_surface(tempbuffdesc, tempbuff);
179 return bverror;
180 }
182 void free_surface(struct bvbuffdesc *bvbuffdesc,
183 void *buffer)
184 {
185 if (bvbuffdesc != NULL) {
186 if (bvbuffdesc->virtaddr != NULL)
187 vfree(bvbuffdesc->virtaddr);
189 if (bvbuffdesc->auxptr != NULL) {
190 struct bvphysdesc *bvphysdesc;
192 bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr;
193 if (bvphysdesc->pagearray != NULL)
194 vfree(bvphysdesc->pagearray);
196 vfree(bvphysdesc);
197 }
199 vfree(bvbuffdesc);
200 }
201 }
204 /*******************************************************************************
205 * Cache operation wrapper.
206 */
208 enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
209 enum bvcacheop cacheop)
210 {
211 enum bverror err = BVERR_NONE;
213 switch (cacheop) {
215 case DMA_FROM_DEVICE:
216 c2dm_l2cache(count, rgn, cacheop);
217 c2dm_l1cache(count, rgn, cacheop);
218 break;
220 case DMA_TO_DEVICE:
221 c2dm_l1cache(count, rgn, cacheop);
222 c2dm_l2cache(count, rgn, cacheop);
223 break;
225 case DMA_BIDIRECTIONAL:
226 c2dm_l1cache(count, rgn, cacheop);
227 c2dm_l2cache(count, rgn, cacheop);
228 break;
230 default:
231 err = BVERR_CACHEOP;
232 break;
233 }
235 return err;
236 }
239 /*******************************************************************************
240 * Device init/cleanup.
241 */
243 static int __init mod_init(void)
244 {
245 bv_init();
247 /* Assign BV function parameters only if SoC contains a GC core */
248 if (cpu_is_omap447x())
249 gcbv_assign();
251 return 0;
252 }
254 static void __exit mod_exit(void)
255 {
256 gcbv_clear();
257 bv_exit();
258 }
260 MODULE_LICENSE("GPL v2");
261 MODULE_AUTHOR("www.vivantecorp.com");
262 MODULE_AUTHOR("www.ti.com");
263 module_init(mod_init);
264 module_exit(mod_exit);