• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * @file        csc.c
20  *
21  * @brief       color space convertion abstract source
22  *
23  * @author      Pyoungjae Jung(pjet.jung@samsung.com)
24  *
25  * @version     1.0.0
26  *
27  * @history
28  *   2012.1.11 : Create
29  */
30 #define LOG_TAG "libcsc"
31 #include <cutils/log.h>
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <utils/Log.h>
36 #include <system/graphics.h>
37 
38 #include "csc.h"
39 #include "exynos_format.h"
40 #include "swconverter.h"
41 
42 #ifdef EXYNOS_OMX
43 #include "Exynos_OMX_Def.h"
44 #else
45 #include "SEC_OMX_Def.h"
46 #endif
47 
48 #ifdef ENABLE_FIMC
49 #include "hwconverter_wrapper.h"
50 #endif
51 
52 #ifdef ENABLE_GSCALER
53 #include "exynos_gscaler.h"
54 #endif
55 
56 #ifdef ENABLE_G2D
57 #include <fcntl.h>
58 #include <sys/ioctl.h>
59 #include "fimg2d.h"
60 
61 typedef struct
62 {
63     struct fimg2d_image src;
64     struct fimg2d_image dst;
65     int fd;
66 } g2d_data;
67 #endif
68 
69 #define GSCALER_IMG_ALIGN 16
70 #define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
71 
72 typedef enum _CSC_PLANE {
73     CSC_Y_PLANE = 0,
74     CSC_RGB_PLANE = 0,
75     CSC_U_PLANE = 1,
76     CSC_UV_PLANE = 1,
77     CSC_V_PLANE = 2
78 } CSC_PLANE;
79 
80 typedef struct _CSC_FORMAT {
81     unsigned int width;
82     unsigned int height;
83     unsigned int crop_left;
84     unsigned int crop_top;
85     unsigned int crop_width;
86     unsigned int crop_height;
87     unsigned int color_format;
88     unsigned int cacheable;
89     unsigned int mode_drm;
90 } CSC_FORMAT;
91 
92 typedef struct _CSC_BUFFER {
93     void *planes[CSC_MAX_PLANES];
94 } CSC_BUFFER;
95 
96 typedef struct _CSC_HW_PROPERTY {
97     int fixed_node;
98     int mode_drm;
99 } CSC_HW_PROPERTY;
100 
101 typedef struct _CSC_HANDLE {
102     CSC_FORMAT      dst_format;
103     CSC_FORMAT      src_format;
104     CSC_BUFFER      dst_buffer;
105     CSC_BUFFER      src_buffer;
106     CSC_METHOD      csc_method;
107     CSC_HW_TYPE     csc_hw_type;
108     void           *csc_hw_handle;
109     CSC_HW_PROPERTY hw_property;
110 } CSC_HANDLE;
111 
112 /* source is RGB888 */
conv_sw_src_argb888(CSC_HANDLE * handle)113 static CSC_ERRORCODE conv_sw_src_argb888(
114     CSC_HANDLE *handle)
115 {
116     CSC_ERRORCODE ret = CSC_ErrorNone;
117 
118     switch (handle->dst_format.color_format) {
119     case HAL_PIXEL_FORMAT_YCbCr_420_P:
120         csc_ARGB8888_to_YUV420P(
121             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
122             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
123             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
124             (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
125             handle->src_format.width,
126             handle->src_format.height);
127         ret = CSC_ErrorNone;
128         break;
129     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
130         csc_ARGB8888_to_YUV420SP_NEON(
131             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
132             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
133             (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE],
134             handle->src_format.width,
135             handle->src_format.height);
136         ret = CSC_ErrorNone;
137         break;
138     default:
139         ret = CSC_ErrorUnsupportFormat;
140         break;
141     }
142 
143     return ret;
144 }
145 
146 /* source is NV12T */
conv_sw_src_nv12t(CSC_HANDLE * handle)147 static CSC_ERRORCODE conv_sw_src_nv12t(
148     CSC_HANDLE *handle)
149 {
150     CSC_ERRORCODE ret = CSC_ErrorNone;
151 
152     switch (handle->dst_format.color_format) {
153     case HAL_PIXEL_FORMAT_YCbCr_420_P:
154         csc_tiled_to_linear_y_neon(
155             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
156             (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
157             handle->src_format.width,
158             handle->src_format.height);
159         csc_tiled_to_linear_uv_deinterleave_neon(
160             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
161             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
162             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
163             handle->src_format.width,
164             handle->src_format.height / 2);
165         ret = CSC_ErrorNone;
166         break;
167     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
168         csc_tiled_to_linear_y_neon(
169             (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
170             (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
171             handle->src_format.width,
172             handle->src_format.height);
173         csc_tiled_to_linear_uv_neon(
174             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
175             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
176             handle->src_format.width,
177             handle->src_format.height / 2);
178         ret = CSC_ErrorNone;
179         break;
180     default:
181         ret = CSC_ErrorUnsupportFormat;
182         break;
183     }
184 
185     return ret;
186 }
187 
188 /* source is YUV420P */
conv_sw_src_yuv420p(CSC_HANDLE * handle)189 static CSC_ERRORCODE conv_sw_src_yuv420p(
190     CSC_HANDLE *handle)
191 {
192     CSC_ERRORCODE ret = CSC_ErrorNone;
193 
194     switch (handle->dst_format.color_format) {
195     case HAL_PIXEL_FORMAT_YCbCr_420_P:  /* bypass */
196         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
197                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
198                handle->src_format.width * handle->src_format.height);
199         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
200                (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
201                (handle->src_format.width * handle->src_format.height) >> 2);
202         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
203                (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
204                (handle->src_format.width * handle->src_format.height) >> 2);
205         ret = CSC_ErrorNone;
206         break;
207     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
208         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
209                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
210                handle->src_format.width * handle->src_format.height);
211         csc_interleave_memcpy_neon(
212             (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
213             (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE],
214             (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE],
215             (handle->src_format.width * handle->src_format.height) >> 2);
216         ret = CSC_ErrorNone;
217         break;
218     default:
219         ret = CSC_ErrorUnsupportFormat;
220         break;
221     }
222 
223     return ret;
224 }
225 
226 /* source is YUV420SP */
conv_sw_src_yuv420sp(CSC_HANDLE * handle)227 static CSC_ERRORCODE conv_sw_src_yuv420sp(
228     CSC_HANDLE *handle)
229 {
230     CSC_ERRORCODE ret = CSC_ErrorNone;
231 
232     switch (handle->dst_format.color_format) {
233     case HAL_PIXEL_FORMAT_YCbCr_420_P:
234         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
235                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
236                handle->src_format.width * handle->src_format.height);
237         csc_deinterleave_memcpy(
238             (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE],
239             (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE],
240             (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
241             handle->src_format.width * handle->src_format.height >> 1);
242         ret = CSC_ErrorNone;
243         break;
244     case HAL_PIXEL_FORMAT_YCbCr_420_SP: /* bypass */
245         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE],
246                (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE],
247                handle->src_format.width * handle->src_format.height);
248         memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE],
249                (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE],
250                handle->src_format.width * handle->src_format.height >> 1);
251         ret = CSC_ErrorNone;
252         break;
253     default:
254         ret = CSC_ErrorUnsupportFormat;
255         break;
256     }
257 
258     return ret;
259 }
260 
conv_sw(CSC_HANDLE * handle)261 static CSC_ERRORCODE conv_sw(
262     CSC_HANDLE *handle)
263 {
264     CSC_ERRORCODE ret = CSC_ErrorNone;
265 
266     switch (handle->src_format.color_format) {
267     case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
268         ret = conv_sw_src_nv12t(handle);
269         break;
270     case HAL_PIXEL_FORMAT_YCbCr_420_P:
271         ret = conv_sw_src_yuv420p(handle);
272         break;
273     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
274         ret = conv_sw_src_yuv420sp(handle);
275         break;
276     case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
277         ret = conv_sw_src_argb888(handle);
278         break;
279     default:
280         ret = CSC_ErrorUnsupportFormat;
281         break;
282     }
283 
284     return ret;
285 }
286 
conv_hw(CSC_HANDLE * handle)287 static CSC_ERRORCODE conv_hw(
288     CSC_HANDLE *handle)
289 {
290     CSC_ERRORCODE ret = CSC_ErrorNone;
291     switch (handle->csc_hw_type) {
292 #ifdef ENABLE_FIMC
293     case CSC_HW_TYPE_FIMC:
294     {
295         void *src_addr[3];
296         void *dst_addr[3];
297         OMX_COLOR_FORMATTYPE src_omx_format;
298         OMX_COLOR_FORMATTYPE dst_omx_format;
299         src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE];
300         src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE];
301         dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE];
302         dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE];
303         dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE];
304         src_omx_format = hal_2_omx_pixel_format(handle->src_format.color_format);
305         dst_omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format);
306         csc_hwconverter_convert_nv12t(
307             handle->csc_hw_handle,
308             dst_addr,
309             src_addr,
310             handle->dst_format.width,
311             handle->dst_format.height,
312             dst_omx_format,
313             src_omx_format);
314         break;
315     }
316 #endif
317 #ifdef ENABLE_GSCALER
318     case CSC_HW_TYPE_GSCALER:
319         if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
320             ALOGE("%s:: exynos_gsc_convert() fail", __func__);
321             ret = CSC_Error;
322         }
323         break;
324 #endif
325 #ifdef ENABLE_G2D
326     case CSC_HW_TYPE_G2D:
327     {
328         g2d_data *g2d = (g2d_data *)handle->csc_hw_handle;
329         struct fimg2d_blit blit;
330         int err;
331 
332         memset(&blit, 0, sizeof(blit));
333         blit.op = BLIT_OP_SRC_COPY;
334         blit.param.g_alpha = 0xFF;
335         blit.src = &g2d->src;
336         blit.dst = &g2d->dst;
337         blit.sync = BLIT_SYNC;
338 
339         err = ioctl(g2d->fd, FIMG2D_BITBLT_BLIT, &blit);
340         if (err < 0) {
341             ALOGE("FIMG2D_BITBLT_BLIT ioctl failed: %s", strerror(errno));
342             ret = CSC_Error;
343         }
344 
345         break;
346     }
347 #endif
348     default:
349         ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
350         ret = CSC_ErrorNotImplemented;
351         break;
352     }
353 
354     return ret;
355 }
356 
csc_init_hw(void * handle)357 static CSC_ERRORCODE csc_init_hw(
358     void *handle)
359 {
360     CSC_HANDLE *csc_handle;
361     CSC_ERRORCODE ret = CSC_ErrorNone;
362 
363     csc_handle = (CSC_HANDLE *)handle;
364     if (csc_handle->csc_method == CSC_METHOD_HW) {
365         switch (csc_handle->csc_hw_type) {
366 #ifdef ENABLE_FIMC
367         case CSC_HW_TYPE_FIMC:
368             csc_handle->csc_hw_handle = csc_hwconverter_open();
369             ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
370             break;
371 #endif
372 #ifdef ENABLE_GSCALER
373         case CSC_HW_TYPE_GSCALER:
374             if (csc_handle->hw_property.fixed_node >= 0)
375                 csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
376             else
377             csc_handle->csc_hw_handle = exynos_gsc_create();
378             ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
379             break;
380 #endif
381 #ifdef ENABLE_G2D
382         case CSC_HW_TYPE_G2D:
383         {
384             g2d_data *g2d = calloc(1, sizeof(g2d_data));
385             if (!g2d) {
386                 ALOGE("failed to allocate G2D data");
387                 break;
388             }
389             g2d->fd = open("/dev/fimg2d", O_RDWR);
390             if (g2d->fd < 0) {
391                 ALOGE("failed to open G2D: %s", strerror(errno));
392                 free(g2d);
393             } else {
394                 csc_handle->csc_hw_handle = g2d;
395             }
396             break;
397         }
398 #endif
399         default:
400             ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
401             csc_handle->csc_hw_handle = NULL;
402             break;
403         }
404     }
405 
406     if (csc_handle->csc_method == CSC_METHOD_HW) {
407         if (csc_handle->csc_hw_handle == NULL) {
408             ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
409             ret = CSC_Error;
410         }
411     }
412 
413     ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
414 
415     return ret;
416 }
417 
csc_set_format(void * handle)418 static CSC_ERRORCODE csc_set_format(
419     void *handle)
420 {
421     CSC_HANDLE *csc_handle;
422     CSC_ERRORCODE ret = CSC_ErrorNone;
423 
424     if (handle == NULL)
425         return CSC_ErrorNotInit;
426 
427     csc_handle = (CSC_HANDLE *)handle;
428     if (csc_handle->csc_method == CSC_METHOD_HW) {
429         switch (csc_handle->csc_hw_type) {
430         case CSC_HW_TYPE_FIMC:
431             break;
432 #ifdef ENABLE_GSCALER
433         case CSC_HW_TYPE_GSCALER:
434             exynos_gsc_set_src_format(
435                 csc_handle->csc_hw_handle,
436                 ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN),
437                 ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN),
438                 csc_handle->src_format.crop_left,
439                 csc_handle->src_format.crop_top,
440                 csc_handle->src_format.crop_width,
441                 csc_handle->src_format.crop_height,
442                 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format),
443                 csc_handle->src_format.cacheable,
444                 csc_handle->hw_property.mode_drm);
445 
446             exynos_gsc_set_dst_format(
447                 csc_handle->csc_hw_handle,
448                 ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN),
449                 ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN),
450                 csc_handle->dst_format.crop_left,
451                 csc_handle->dst_format.crop_top,
452                 csc_handle->dst_format.crop_width,
453                 csc_handle->dst_format.crop_height,
454                 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
455                 csc_handle->dst_format.cacheable,
456                 csc_handle->hw_property.mode_drm,
457                 0);
458             break;
459 #endif
460 #ifdef ENABLE_G2D
461         case CSC_HW_TYPE_G2D:
462         {
463             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
464 
465             g2d->src.width = ALIGN(csc_handle->src_format.width,
466                     GSCALER_IMG_ALIGN);
467             g2d->src.height = csc_handle->src_format.height;
468             g2d->src.stride = g2d->src.width *
469                     hal_2_g2d_bpp(csc_handle->src_format.color_format) >> 3;
470             g2d->src.order = hal_2_g2d_pixel_order(csc_handle->src_format.color_format);
471             g2d->src.fmt = hal_2_g2d_color_format(csc_handle->src_format.color_format);
472             g2d->src.rect.x1 = csc_handle->src_format.crop_left;
473             g2d->src.rect.y1 = csc_handle->src_format.crop_top;
474             g2d->src.rect.x2 = csc_handle->src_format.crop_left +
475                     csc_handle->src_format.crop_width;
476             g2d->src.rect.y2 = csc_handle->src_format.crop_top +
477                     csc_handle->src_format.crop_height;
478 
479             g2d->dst.width = ALIGN(csc_handle->dst_format.width,
480                     GSCALER_IMG_ALIGN);
481             g2d->dst.height = csc_handle->dst_format.height;
482             g2d->dst.stride = g2d->dst.width *
483                     hal_2_g2d_bpp(csc_handle->dst_format.color_format) >> 3;
484             g2d->dst.order = hal_2_g2d_pixel_order(csc_handle->dst_format.color_format);
485             g2d->dst.fmt = hal_2_g2d_color_format(csc_handle->dst_format.color_format);
486             g2d->dst.rect.x1 = csc_handle->dst_format.crop_left;
487             g2d->dst.rect.y1 = csc_handle->dst_format.crop_top;
488             g2d->dst.rect.x2 = csc_handle->dst_format.crop_left +
489                     csc_handle->dst_format.crop_width;
490             g2d->dst.rect.y2 = csc_handle->dst_format.crop_top +
491                     csc_handle->dst_format.crop_height;
492 
493             break;
494         }
495 #endif
496         default:
497             ALOGE("%s:: unsupported csc_hw_type", __func__);
498             break;
499         }
500     }
501 
502     return ret;
503 }
504 
csc_set_buffer(void * handle)505 static CSC_ERRORCODE csc_set_buffer(
506     void *handle)
507 {
508     CSC_HANDLE *csc_handle;
509     CSC_ERRORCODE ret = CSC_ErrorNone;
510 
511     if (handle == NULL)
512         return CSC_ErrorNotInit;
513 
514     csc_handle = (CSC_HANDLE *)handle;
515     if (csc_handle->csc_method == CSC_METHOD_HW) {
516         switch (csc_handle->csc_hw_type) {
517         case CSC_HW_TYPE_FIMC:
518             break;
519 #ifdef ENABLE_GSCALER
520         case CSC_HW_TYPE_GSCALER:
521             exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1);
522             exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1);
523             break;
524 #endif
525 #ifdef ENABLE_G2D
526         case CSC_HW_TYPE_G2D:
527         {
528             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
529 
530             g2d->src.addr.type = ADDR_DMA_BUF;
531             g2d->src.addr.fd[0] = (int)csc_handle->src_buffer.planes[0];
532             g2d->src.addr.fd[1] = (int)csc_handle->src_buffer.planes[1];
533 
534             g2d->dst.addr.type = ADDR_DMA_BUF;
535             g2d->dst.addr.fd[0] = (int)csc_handle->dst_buffer.planes[0];
536             g2d->dst.addr.fd[1] = (int)csc_handle->dst_buffer.planes[1];
537 
538             break;
539         }
540 #endif
541         default:
542             ALOGE("%s:: unsupported csc_hw_type", __func__);
543             break;
544         }
545     }
546 
547     return ret;
548 }
549 
csc_init(CSC_METHOD method)550 void *csc_init(
551     CSC_METHOD method)
552 {
553     CSC_HANDLE *csc_handle;
554     csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE));
555     if (csc_handle == NULL)
556         return NULL;
557 
558     memset(csc_handle, 0, sizeof(CSC_HANDLE));
559     csc_handle->hw_property.fixed_node = -1;
560     csc_handle->hw_property.mode_drm = 0;
561     csc_handle->csc_method = method;
562 
563     return (void *)csc_handle;
564 }
565 
csc_deinit(void * handle)566 CSC_ERRORCODE csc_deinit(
567     void *handle)
568 {
569     CSC_ERRORCODE ret = CSC_ErrorNone;
570     CSC_HANDLE *csc_handle;
571 
572     csc_handle = (CSC_HANDLE *)handle;
573     if (csc_handle->csc_hw_handle) {
574         switch (csc_handle->csc_hw_type) {
575 #ifdef ENABLE_FIMC
576         case CSC_HW_TYPE_FIMC:
577             csc_hwconverter_close(csc_handle->csc_hw_handle);
578             break;
579 #endif
580 #ifdef ENABLE_GSCALER
581         case CSC_HW_TYPE_GSCALER:
582             exynos_gsc_destroy(csc_handle->csc_hw_handle);
583             break;
584 #endif
585 #ifdef ENABLE_G2D
586         case CSC_HW_TYPE_G2D:
587         {
588             g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle;
589             close(g2d->fd);
590             free(g2d);
591             break;
592         }
593 #endif
594         default:
595             ALOGE("%s:: unsupported csc_hw_type", __func__);
596             break;
597         }
598     }
599 
600     if (csc_handle != NULL) {
601         free(csc_handle);
602         ret = CSC_ErrorNone;
603     }
604 
605     return ret;
606 }
607 
csc_get_method(void * handle,CSC_METHOD * method)608 CSC_ERRORCODE csc_get_method(
609     void           *handle,
610     CSC_METHOD     *method)
611 {
612     CSC_HANDLE *csc_handle;
613     CSC_ERRORCODE ret = CSC_ErrorNone;
614 
615     if (handle == NULL)
616         return CSC_ErrorNotInit;
617 
618     csc_handle = (CSC_HANDLE *)handle;
619     *method = csc_handle->csc_method;
620 
621     return ret;
622 }
623 
csc_set_method(void * handle,CSC_METHOD method)624 CSC_ERRORCODE csc_set_method(
625     void           *handle,
626     CSC_METHOD     method)
627 {
628     CSC_HANDLE *csc_handle;
629     CSC_ERRORCODE ret = CSC_ErrorNone;
630 
631     if (handle == NULL)
632         return CSC_ErrorNotInit;
633 
634     csc_handle = (CSC_HANDLE *)handle;
635     csc_handle->csc_method = method;
636 
637     return ret;
638 }
639 
csc_set_hw_property(void * handle,CSC_HW_PROPERTY_TYPE property,int value)640 CSC_ERRORCODE csc_set_hw_property(
641     void                *handle,
642     CSC_HW_PROPERTY_TYPE property,
643     int                  value)
644 {
645     CSC_HANDLE *csc_handle;
646     CSC_ERRORCODE ret = CSC_ErrorNone;
647 
648     if (handle == NULL)
649         return CSC_ErrorNotInit;
650 
651     csc_handle = (CSC_HANDLE *)handle;
652 
653     if (csc_handle->csc_hw_handle) {
654         ALOGE("%s:: cannot set hw property after hw is already initialized", __func__);
655         return CSC_ErrorUnsupportFormat;
656     }
657 
658     switch (property) {
659     case CSC_HW_PROPERTY_FIXED_NODE:
660         csc_handle->hw_property.fixed_node = value;
661         break;
662     case CSC_HW_PROPERTY_MODE_DRM:
663         csc_handle->hw_property.mode_drm = value;
664         break;
665     case CSC_HW_PROPERTY_HW_TYPE:
666         csc_handle->csc_hw_type = value;
667         break;
668     default:
669         ALOGE("%s:: not supported hw property", __func__);
670         ret = CSC_ErrorUnsupportFormat;
671     }
672 
673     return ret;
674 }
675 
csc_get_src_format(void * handle,unsigned int * width,unsigned int * height,unsigned int * crop_left,unsigned int * crop_top,unsigned int * crop_width,unsigned int * crop_height,unsigned int * color_format,unsigned int * cacheable)676 CSC_ERRORCODE csc_get_src_format(
677     void           *handle,
678     unsigned int   *width,
679     unsigned int   *height,
680     unsigned int   *crop_left,
681     unsigned int   *crop_top,
682     unsigned int   *crop_width,
683     unsigned int   *crop_height,
684     unsigned int   *color_format,
685     unsigned int   *cacheable)
686 {
687     CSC_HANDLE *csc_handle;
688     CSC_ERRORCODE ret = CSC_ErrorNone;
689 
690     if (handle == NULL)
691         return CSC_ErrorNotInit;
692 
693     csc_handle = (CSC_HANDLE *)handle;
694     *width = csc_handle->src_format.width;
695     *height = csc_handle->src_format.height;
696     *crop_left = csc_handle->src_format.crop_left;
697     *crop_top = csc_handle->src_format.crop_top;
698     *crop_width = csc_handle->src_format.crop_width;
699     *crop_height = csc_handle->src_format.crop_height;
700     *color_format = csc_handle->src_format.color_format;
701     *cacheable = csc_handle->src_format.cacheable;
702 
703     return ret;
704 }
705 
csc_set_src_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int color_format,unsigned int cacheable)706 CSC_ERRORCODE csc_set_src_format(
707     void           *handle,
708     unsigned int    width,
709     unsigned int    height,
710     unsigned int    crop_left,
711     unsigned int    crop_top,
712     unsigned int    crop_width,
713     unsigned int    crop_height,
714     unsigned int    color_format,
715     unsigned int    cacheable)
716 {
717     CSC_HANDLE *csc_handle;
718     CSC_ERRORCODE ret = CSC_ErrorNone;
719 
720     if (handle == NULL)
721         return CSC_ErrorNotInit;
722 
723     csc_handle = (CSC_HANDLE *)handle;
724     csc_handle->src_format.width = width;
725     csc_handle->src_format.height = height;
726     csc_handle->src_format.crop_left = crop_left;
727     csc_handle->src_format.crop_top = crop_top;
728     csc_handle->src_format.crop_width = crop_width;
729     csc_handle->src_format.crop_height = crop_height;
730     csc_handle->src_format.color_format = color_format;
731     csc_handle->src_format.cacheable = cacheable;
732 
733     return ret;
734 }
735 
csc_get_dst_format(void * handle,unsigned int * width,unsigned int * height,unsigned int * crop_left,unsigned int * crop_top,unsigned int * crop_width,unsigned int * crop_height,unsigned int * color_format,unsigned int * cacheable)736 CSC_ERRORCODE csc_get_dst_format(
737     void           *handle,
738     unsigned int   *width,
739     unsigned int   *height,
740     unsigned int   *crop_left,
741     unsigned int   *crop_top,
742     unsigned int   *crop_width,
743     unsigned int   *crop_height,
744     unsigned int   *color_format,
745     unsigned int   *cacheable)
746 {
747     CSC_HANDLE *csc_handle;
748     CSC_ERRORCODE ret = CSC_ErrorNone;
749 
750     if (handle == NULL)
751         return CSC_ErrorNotInit;
752 
753     csc_handle = (CSC_HANDLE *)handle;
754     *width = csc_handle->dst_format.width;
755     *height = csc_handle->dst_format.height;
756     *crop_left = csc_handle->dst_format.crop_left;
757     *crop_top = csc_handle->dst_format.crop_top;
758     *crop_width = csc_handle->dst_format.crop_width;
759     *crop_height = csc_handle->dst_format.crop_height;
760     *color_format = csc_handle->dst_format.color_format;
761     *cacheable = csc_handle->dst_format.cacheable;
762 
763     return ret;
764 }
765 
csc_set_dst_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int color_format,unsigned int cacheable)766 CSC_ERRORCODE csc_set_dst_format(
767     void           *handle,
768     unsigned int    width,
769     unsigned int    height,
770     unsigned int    crop_left,
771     unsigned int    crop_top,
772     unsigned int    crop_width,
773     unsigned int    crop_height,
774     unsigned int    color_format,
775     unsigned int    cacheable)
776 {
777     CSC_HANDLE *csc_handle;
778     CSC_ERRORCODE ret = CSC_ErrorNone;
779 
780     if (handle == NULL)
781         return CSC_ErrorNotInit;
782 
783     csc_handle = (CSC_HANDLE *)handle;
784     csc_handle->dst_format.width = width;
785     csc_handle->dst_format.height = height;
786     csc_handle->dst_format.crop_left = crop_left;
787     csc_handle->dst_format.crop_top = crop_top;
788     csc_handle->dst_format.crop_width = crop_width;
789     csc_handle->dst_format.crop_height = crop_height;
790     csc_handle->dst_format.color_format = color_format;
791     csc_handle->dst_format.cacheable = cacheable;
792 
793     return ret;
794 }
795 
csc_set_src_buffer(void * handle,void * addr[3])796 CSC_ERRORCODE csc_set_src_buffer(
797     void *handle,
798     void *addr[3])
799 {
800     CSC_HANDLE *csc_handle;
801     CSC_ERRORCODE ret = CSC_ErrorNone;
802 
803     if (handle == NULL)
804         return CSC_ErrorNotInit;
805 
806     csc_handle = (CSC_HANDLE *)handle;
807     csc_handle->src_buffer.planes[CSC_Y_PLANE] = addr[0];
808     csc_handle->src_buffer.planes[CSC_U_PLANE] = addr[1];
809     csc_handle->src_buffer.planes[CSC_V_PLANE] = addr[2];
810 
811     return ret;
812 }
813 
csc_set_dst_buffer(void * handle,void * addr[3])814 CSC_ERRORCODE csc_set_dst_buffer(
815     void *handle,
816     void *addr[3])
817 {
818     CSC_HANDLE *csc_handle;
819     CSC_ERRORCODE ret = CSC_ErrorNone;
820 
821     if (handle == NULL)
822         return CSC_ErrorNotInit;
823 
824     csc_handle = (CSC_HANDLE *)handle;
825     csc_handle->dst_buffer.planes[CSC_Y_PLANE] = addr[0];
826     csc_handle->dst_buffer.planes[CSC_U_PLANE] = addr[1];
827     csc_handle->dst_buffer.planes[CSC_V_PLANE] = addr[2];
828 
829     return ret;
830 }
831 
csc_convert(void * handle)832 CSC_ERRORCODE csc_convert(
833     void *handle)
834 {
835     CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle;
836     CSC_ERRORCODE ret = CSC_ErrorNone;
837 
838     if (csc_handle == NULL)
839         return CSC_ErrorNotInit;
840 
841     if ((csc_handle->csc_method == CSC_METHOD_HW) &&
842         (csc_handle->csc_hw_handle == NULL)) {
843         ret = csc_init_hw(handle);
844         if (ret != CSC_ErrorNone)
845             return ret;
846     }
847 
848     ret = csc_set_format(csc_handle);
849     if (ret != CSC_ErrorNone)
850         return ret;
851 
852     ret = csc_set_buffer(csc_handle);
853     if (ret != CSC_ErrorNone)
854         return ret;
855 
856     if (csc_handle->csc_method == CSC_METHOD_HW)
857         ret = conv_hw(csc_handle);
858     else
859         ret = conv_sw(csc_handle);
860 
861     return ret;
862 }
863