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 (at) 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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