fee3c54e9429ce61fc49fca62ebf133cf7e61206
1 /*
2 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
35 /* This file defines the function to program the GC320 IP */
37 #include <stdint.h>
38 #include "cmem_buf.h"
39 #include "gc320.h"
40 #include "error.h"
41 #include "cmem_buf.h"
43 /* Configure one time the source and destination surface context for all buffers
44 * as they cost some performance overhead if configured per frame. Since the
45 * buffer parameters aren't changing in this application run time, we can save the overhead
46 */
47 Gc320Obj::Gc320Obj(uint32_t num_src_surf, uint32_t num_dst_surf, BufObj *src_bo, BufObj *dst_bo){
48 m_dst_width = dst_bo->m_width;
49 m_dst_height = dst_bo->m_height;
50 m_dst_stride = dst_bo->m_stride;
51 m_dst_format = gcvSURF_UYVY;
53 m_src_width = src_bo->m_width;
54 m_src_height = src_bo->m_height;
55 m_src_stride = src_bo->m_stride;
56 m_src_format = gcvSURF_UYVY;
58 m_src_surf_ctxt = (surf_context *) malloc(num_src_surf * sizeof(surf_context));
59 m_dst_surf_ctxt = (surf_context *) malloc(num_src_surf * sizeof(surf_context));
61 init_gc320();
63 configure_surface(m_src_surf_ctxt, num_src_surf, src_bo, m_src_format);
64 configure_surface(m_dst_surf_ctxt, num_dst_surf, dst_bo, m_dst_format);
65 }
68 /*
69 * ~Gc320Obj() //Class destructor
70 * free all resources
71 */
72 Gc320Obj::~Gc320Obj(){
73 if (m_hal != gcvNULL){
74 gcoHAL_Commit(m_hal, true);
75 }
77 for(uint32_t i = 0; i < m_num_dst_ctx; i++){
78 if (m_dst_surf_ctxt[i].surf != gcvNULL){
79 gceHARDWARE_TYPE type;
81 gcoHAL_GetHardwareType(gcvNULL, &type);
83 gcmVERIFY_OK(gcoSURF_Unlock(m_dst_surf_ctxt[i].surf, gcvNULL));
84 gcmVERIFY_OK(gcoSURF_Destroy(m_dst_surf_ctxt[i].surf));
85 gcmVERIFY_OK(gcoHAL_Commit(gcvNULL, true));
87 gcoHAL_SetHardwareType(gcvNULL, type);
88 }
89 }
91 for(uint32_t i = 0; i < m_num_src_ctx; i++){
92 if (m_src_surf_ctxt[i].surf != gcvNULL){
93 gceHARDWARE_TYPE type;
95 gcoHAL_GetHardwareType(gcvNULL, &type);
97 gcmVERIFY_OK(gcoSURF_Unlock(m_src_surf_ctxt[i].surf, gcvNULL));
98 gcmVERIFY_OK(gcoSURF_Destroy(m_src_surf_ctxt[i].surf));
99 gcmVERIFY_OK(gcoHAL_Commit(gcvNULL, true));
101 gcoHAL_SetHardwareType(gcvNULL, type);
102 }
103 }
105 if (m_hal != gcvNULL){
106 gcoHAL_Commit(m_hal, true);
107 gcoHAL_Destroy(m_hal);
108 }
110 if (m_os != gcvNULL){
111 gcoOS_Destroy(m_os);
112 }
113 }
116 int Gc320Obj::chip_check(){
117 gceSTATUS status;
118 uint32_t i;
119 int ret = 0;
120 gceCHIPMODEL chip_model;
121 uint32_t chip_revision;
122 uint32_t patch_revision;
123 uint32_t chip_features;
124 uint32_t chip_minor_features_number;
125 uint32_t chip_minor_features[MAX_MINORFEATURE_NUMBER];
127 status = gcoHAL_QueryChipIdentity(m_hal, &chip_model, &chip_revision, &chip_features, gcvNULL);
128 if (status < 0){
129 ERROR("Failed to query chip info (status = 0x%x)\n", status);
130 ret = -1;
131 goto EXIT;
132 }
134 status = gcoOS_ReadRegister(m_os, 0x98, &patch_revision);
135 if (status < 0){
136 ERROR("Failed to read patch version (status = 0x%x)\n", status);
137 ret = -2;
138 goto EXIT;
139 }
141 MSG("=================== Chip Information ==================\n");
142 MSG("Chip : GC%x\n", chip_model);
143 MSG("Chip revision: 0x%08x\n", chip_revision);
144 MSG( "Patch revision: 0x%08x\n", patch_revision);
145 MSG("Chip Features: 0x%08x\n", chip_features);
147 status = gcoHAL_QueryChipMinorFeatures(m_hal, &chip_minor_features_number, gcvNULL);
148 if (status < 0){
149 ERROR("Failed to query minor feature count (status = 0x%x)\n", status);
150 ret = -2;
151 goto EXIT;
152 }
154 if (MAX_MINORFEATURE_NUMBER < chip_minor_features_number){
155 ERROR("no enough space for minor features\n");
156 ret = -3;
157 goto EXIT;
158 }
160 status = gcoHAL_QueryChipMinorFeatures(m_hal, &chip_minor_features_number, chip_minor_features);
161 if (status < 0){
162 ERROR("Failed to query minor features (status = 0x%x)\n", status);
163 ret = -4;
164 goto EXIT;
165 }
167 for (i = 0; i < chip_minor_features_number; i++){
168 MSG("Chip MinorFeatures%d: 0x%08x\n", i, chip_minor_features[i]);
169 }
171 MSG("=======================================================\n");
173 EXIT:
175 return ret;
176 }
178 int Gc320Obj::init_gc320() {
180 gceSTATUS status;
182 /* Construct the gcoOS object. */
183 status = gcoOS_Construct(gcvNULL, &m_os);
184 if (status < 0){
185 ERROR("Failed to construct OS object (status = %d)\n", status);
186 return false;
187 }
189 /* Construct the gcoHAL object. */
190 status = gcoHAL_Construct(gcvNULL, m_os, &m_hal);
191 if (status < 0){
192 ERROR("Failed to construct GAL object (status = %d)\n", status);
193 return false;
194 }
196 if (!gcoHAL_IsFeatureAvailable(m_hal, gcvFEATURE_2DPE20)){
198 switch (m_dst_format){
199 /* PE1.0 support. */
200 case gcvSURF_X4R4G4B4:
201 case gcvSURF_A4R4G4B4:
202 case gcvSURF_X1R5G5B5:
203 case gcvSURF_A1R5G5B5:
204 case gcvSURF_X8R8G8B8:
205 case gcvSURF_A8R8G8B8:
206 case gcvSURF_R5G6B5:
207 break;
209 default:
210 ERROR("the target format %d is not supported by the hardware.\n",
211 m_dst_format);
212 return false;
213 }
214 }
216 status = gcoHAL_Get2DEngine(m_hal, &m_engine2d);
217 MSG("****GC320 m_engine2d = %x\n", (uint32_t) m_engine2d);
218 if (status < 0){
219 ERROR("Failed to get 2D engine object (status = %d)\n", status);
220 return false;
221 }
223 if (chip_check() < 0){
224 ERROR("Check chip info failed!\n");
225 return false;
226 }
228 return true;
229 }
231 int Gc320Obj::configure_surface(surf_context *surf_ctx,
232 uint32_t num_ctx, BufObj *bo, gceSURF_FORMAT surf_format) {
234 gceSTATUS status;
235 gceHARDWARE_TYPE type;
236 unsigned long phys = ~0U;
238 gcoHAL_GetHardwareType(gcvNULL, &type);
240 for(uint32_t i = 0; i < num_ctx; i++){
241 if (!bo->m_buf[i]) {
242 ERROR("Received null pointer\n");
243 return -1;
244 }
245 /* create a wrapper gcoSURF surface object, because we are mapping the user
246 * allocated buffer pool should be gcvPOOL_USER */
247 status = gcoSURF_Construct(
248 gcvNULL,
249 bo->m_width,
250 bo->m_height,
251 1,
252 gcvSURF_BITMAP,
253 surf_format,
254 gcvPOOL_USER,
255 &surf_ctx[i].surf);
257 if (status < 0) {
258 ERROR(" Failed to create gcoSURF object\n");
259 return false;
260 }
262 /* calculate the size of the buffer needed. Use gcoSURF_QueryFormat API to
263 * format parameters descriptor - this contains information on format as
264 * needed by the Vivante driver
265 */
266 uint32_t width, height;
267 int stride;
268 gcmONERROR(gcoSURF_GetAlignedSize(surf_ctx[i].surf,
269 &width,
270 &height,
271 &stride));
273 if((width != bo->m_width) || (height != bo->m_height) || ((uint32_t) stride != bo->m_stride)){
274 ERROR("Allocated Surf buffer width %d, height %d and stride %d doesn't meet GC320 aligned requirement on width %d, height %d and stride %d\n",
275 bo->m_width, bo->m_height, bo->m_stride, width, height, stride);
276 }
278 uint32_t p_adr_al;
279 gcmONERROR(gcoSURF_GetAlignment(gcvSURF_BITMAP, surf_format,
280 &p_adr_al,
281 NULL, //&p_x_al,
282 NULL //&p_y_al)
283 ));
285 if((uint32_t)bo->m_buf[i] % p_adr_al){
286 ERROR("Buffer passed to GC320 doesn't meet the alignment requirement, GC320 alignment need is %x, received buffer with %x aligned address\n",
287 p_adr_al, ((uint32_t)bo->m_buf[i]%p_adr_al));
288 }
290 /* Buffer provided meets all the requirement from GC320.
291 Go ahead and set the underlying buffer */
292 gcmONERROR(gcoSURF_SetBuffer(
293 surf_ctx[i].surf,
294 gcvSURF_BITMAP,
295 surf_format,
296 bo->m_stride,
297 bo->m_buf[i],
298 phys));
300 if (status < 0) {
301 ERROR("Failed to set buffer for gcoSURF object\n");
302 return false;
303 }
305 /* set window size */
306 gcmONERROR(gcoSURF_SetWindow(surf_ctx[i].surf, 0, 0, bo->m_width, bo->m_height));
307 if (status < 0) {
308 ERROR("Failed to set window for gcoSURF object\n");
309 return false;
310 }
312 /* lock surface */
313 gcmONERROR(gcoSURF_Lock(surf_ctx[i].surf, surf_ctx[i].phys_address, &bo->m_buf[i]));
314 if (status < 0) {
315 ERROR("Failed to lock gcoSURF object\n");
316 return false;
317 }
319 gcoHAL_SetHardwareType(gcvNULL, type);
320 }
322 return true;
324 OnError:
325 ERROR("Failed: %s\n", gcoOS_DebugStatus2Name(status));
327 return false;
328 }
330 bool Gc320Obj::rotation_90deg(uint32_t src_surf_indx, uint32_t dst_surf_indx){
332 gcsRECT src_rect, dst_rect, clip_rect;
333 gceSTATUS status = gcvSTATUS_OK;
335 // render to dest surface
336 // blit with 90 rotation
337 src_rect.left = 0;
338 src_rect.top = 0;
339 src_rect.right = m_src_width;
340 src_rect.bottom = m_src_height;
342 // set the clipping according to the rotation
343 clip_rect.left = 0;
344 clip_rect.top = 0;
345 clip_rect.right = m_dst_height;
346 clip_rect.bottom = m_dst_width;
348 gcmONERROR(gco2D_SetClipping(m_engine2d, &clip_rect));
350 //Since the buffer is getting rotated 90 degree, make sure the destination buffer width is larger than source buffer height */
351 dst_rect.left = 0;
352 dst_rect.top = (m_dst_width - m_src_height);
353 dst_rect.right = dst_rect.left + m_src_width;
354 dst_rect.bottom = dst_rect.top + m_src_height;
356 gcmONERROR(gco2D_SetGenericSource(m_engine2d,
357 m_src_surf_ctxt[src_surf_indx].phys_address, 1, &m_src_stride, 1,
358 gcvLINEAR, m_src_format, gcvSURF_0_DEGREE,
359 m_src_width, m_src_height));
361 gcmONERROR(gco2D_SetSource(m_engine2d, &src_rect));
363 gcmONERROR(gco2D_SetTarget(m_engine2d,
364 m_dst_surf_ctxt[dst_surf_indx].phys_address[0],
365 m_dst_stride,
366 gcvSURF_90_DEGREE,
367 m_dst_width));
369 gcmONERROR(gco2D_Blit(m_engine2d,
370 1,
371 &dst_rect,
372 0xCC,
373 0xCC,
374 m_dst_format));
375 gcmONERROR(gco2D_Flush(m_engine2d));
376 gcmONERROR(gcoHAL_Commit(m_hal, true));
378 return true;
380 OnError:
381 ERROR("Failed: %s\n", gcoOS_DebugStatus2Name(status));
382 return false;
383 }