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