d619641e984f5e13d63832a97582da67629e1e49
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libcsc / csc.c
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 #include <errno.h>
33
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <utils/Log.h>
38 #include <system/graphics.h>
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
50 #ifdef ENABLE_FIMC
51 #include "hwconverter_wrapper.h"
52 #endif
53
54 #ifdef ENABLE_GSCALER
55 #include "exynos_gscaler.h"
56 #endif
57
58 #ifdef ENABLE_G2D
59 #include <fcntl.h>
60 #include <sys/ioctl.h>
61 #include "fimg2d.h"
62
63 typedef struct
64 {
65 struct fimg2d_image src;
66 struct fimg2d_image dst;
67 int fd;
68 } g2d_data;
69 #endif
70
71 #define GSCALER_IMG_ALIGN 16
72 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
73
74 typedef 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
82 typedef 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;
91 unsigned int mode_drm;
92 } CSC_FORMAT;
93
94 typedef struct _CSC_BUFFER {
95 void *planes[CSC_MAX_PLANES];
96 } CSC_BUFFER;
97
98 typedef struct _CSC_HW_PROPERTY {
99 int fixed_node;
100 int mode_drm;
101 } CSC_HW_PROPERTY;
102
103 typedef 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;
111 CSC_HW_PROPERTY hw_property;
112 } CSC_HANDLE;
113
114 /* source is RGB888 */
115 static 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 */
149 static 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 */
191 static 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 */
229 static 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
263 static 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;
278 case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
279 ret = conv_sw_src_argb888(handle);
280 break;
281 default:
282 ret = CSC_ErrorUnsupportFormat;
283 break;
284 }
285
286 return ret;
287 }
288
289 static CSC_ERRORCODE conv_hw(
290 CSC_HANDLE *handle)
291 {
292 CSC_ERRORCODE ret = CSC_ErrorNone;
293 switch (handle->csc_hw_type) {
294 #ifdef ENABLE_FIMC
295 case CSC_HW_TYPE_FIMC:
296 {
297 void *src_addr[3];
298 void *dst_addr[3];
299 OMX_COLOR_FORMATTYPE src_omx_format;
300 OMX_COLOR_FORMATTYPE dst_omx_format;
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];
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);
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,
314 dst_omx_format,
315 src_omx_format);
316 break;
317 }
318 #endif
319 #ifdef ENABLE_GSCALER
320 case CSC_HW_TYPE_GSCALER:
321 if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
322 ALOGE("%s:: exynos_gsc_convert() fail", __func__);
323 ret = CSC_Error;
324 }
325 break;
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 }
349 #endif
350 default:
351 ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
352 ret = CSC_ErrorNotImplemented;
353 break;
354 }
355
356 return ret;
357 }
358
359 static CSC_ERRORCODE csc_init_hw(
360 void *handle)
361 {
362 CSC_HANDLE *csc_handle;
363 CSC_ERRORCODE ret = CSC_ErrorNone;
364
365 csc_handle = (CSC_HANDLE *)handle;
366 if (csc_handle->csc_method == CSC_METHOD_HW) {
367 switch (csc_handle->csc_hw_type) {
368 #ifdef ENABLE_FIMC
369 case CSC_HW_TYPE_FIMC:
370 csc_handle->csc_hw_handle = csc_hwconverter_open();
371 ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
372 break;
373 #endif
374 #ifdef ENABLE_GSCALER
375 case CSC_HW_TYPE_GSCALER:
376 if (csc_handle->hw_property.fixed_node >= 0)
377 csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
378 else
379 csc_handle->csc_hw_handle = exynos_gsc_create();
380 ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
381 break;
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 }
400 #endif
401 default:
402 ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
403 csc_handle->csc_hw_handle = NULL;
404 break;
405 }
406 }
407
408 if (csc_handle->csc_method == CSC_METHOD_HW) {
409 if (csc_handle->csc_hw_handle == NULL) {
410 ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
411 ret = CSC_Error;
412 }
413 }
414
415 ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
416
417 return ret;
418 }
419
420 static 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,
442 csc_handle->src_format.crop_width,
443 csc_handle->src_format.crop_height,
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,
454 csc_handle->dst_format.crop_width,
455 csc_handle->dst_format.crop_height,
456 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
457 csc_handle->dst_format.cacheable,
458 csc_handle->hw_property.mode_drm,
459 0);
460 break;
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 }
497 #endif
498 default:
499 ALOGE("%s:: unsupported csc_hw_type", __func__);
500 break;
501 }
502 }
503
504 return ret;
505 }
506
507 static CSC_ERRORCODE csc_set_buffer(
508 void *handle)
509 {
510 CSC_HANDLE *csc_handle;
511 CSC_ERRORCODE ret = CSC_ErrorNone;
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) {
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:
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);
525 break;
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 }
542 #endif
543 default:
544 ALOGE("%s:: unsupported csc_hw_type", __func__);
545 break;
546 }
547 }
548
549 return ret;
550 }
551
552 void *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;
564
565 return (void *)csc_handle;
566 }
567
568 CSC_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;
575 if (csc_handle->csc_hw_handle) {
576 switch (csc_handle->csc_hw_type) {
577 #ifdef ENABLE_FIMC
578 case CSC_HW_TYPE_FIMC:
579 csc_hwconverter_close(csc_handle->csc_hw_handle);
580 break;
581 #endif
582 #ifdef ENABLE_GSCALER
583 case CSC_HW_TYPE_GSCALER:
584 exynos_gsc_destroy(csc_handle->csc_hw_handle);
585 break;
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 }
595 #endif
596 default:
597 ALOGE("%s:: unsupported csc_hw_type", __func__);
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
610 CSC_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
626 CSC_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
642 CSC_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;
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
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;
667 case CSC_HW_PROPERTY_HW_TYPE:
668 csc_handle->csc_hw_type = value;
669 break;
670 default:
671 ALOGE("%s:: not supported hw property", __func__);
672 ret = CSC_ErrorUnsupportFormat;
673 }
674
675 return ret;
676 }
677
678 CSC_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
708 CSC_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
735 return ret;
736 }
737
738 CSC_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
768 CSC_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
795 return ret;
796 }
797
798 CSC_ERRORCODE csc_set_src_buffer(
799 void *handle,
800 void *addr[3])
801 {
802 CSC_HANDLE *csc_handle;
803 CSC_ERRORCODE ret = CSC_ErrorNone;
804
805 if (handle == NULL)
806 return CSC_ErrorNotInit;
807
808 csc_handle = (CSC_HANDLE *)handle;
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];
812
813 return ret;
814 }
815
816 CSC_ERRORCODE csc_set_dst_buffer(
817 void *handle,
818 void *addr[3])
819 {
820 CSC_HANDLE *csc_handle;
821 CSC_ERRORCODE ret = CSC_ErrorNone;
822
823 if (handle == NULL)
824 return CSC_ErrorNotInit;
825
826 csc_handle = (CSC_HANDLE *)handle;
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];
830
831 return ret;
832 }
833
834 CSC_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
843 if ((csc_handle->csc_method == CSC_METHOD_HW) &&
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;
853
854 ret = csc_set_buffer(csc_handle);
855 if (ret != CSC_ErrorNone)
856 return ret;
857
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 }