]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-linux/video-graphics-test.git/blob - gc320.cpp
fee3c54e9429ce61fc49fca62ebf133cf7e61206
[sitara-linux/video-graphics-test.git] / gc320.cpp
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     }
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;
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;
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;
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;