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