blob: 0831f612b1ecc5e446f4d376dcbdca8c4ae8560a [file] [log] [blame]
Jiho Chang47bd9532012-03-24 05:56:11 +09001/*
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>
Jiho Chang3b540842012-04-26 13:39:20 -070036#include <system/graphics.h>
Jiho Chang47bd9532012-03-24 05:56:11 +090037
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
Jiho Chang3b540842012-04-26 13:39:20 -070048#ifdef ENABLE_FIMC
Jiho Chang47bd9532012-03-24 05:56:11 +090049#include "hwconverter_wrapper.h"
50#endif
51
Jiho Chang3b540842012-04-26 13:39:20 -070052#ifdef ENABLE_GSCALER
Jiho Chang47bd9532012-03-24 05:56:11 +090053#include "exynos_gscaler.h"
54#endif
55
Greg Hackmann8f10f922013-01-14 15:54:46 -080056#ifdef ENABLE_G2D
57#include <fcntl.h>
58#include <sys/ioctl.h>
59#include "fimg2d.h"
60
61typedef struct
62{
63 struct fimg2d_image src;
64 struct fimg2d_image dst;
65 int fd;
66} g2d_data;
67#endif
68
Jiho Chang47bd9532012-03-24 05:56:11 +090069#define GSCALER_IMG_ALIGN 16
Jiho Chang47bd9532012-03-24 05:56:11 +090070#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
71
72typedef 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
Jiho Chang47bd9532012-03-24 05:56:11 +090080typedef 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;
Jiho Chang3b540842012-04-26 13:39:20 -070089 unsigned int mode_drm;
Jiho Chang47bd9532012-03-24 05:56:11 +090090} CSC_FORMAT;
91
92typedef struct _CSC_BUFFER {
SeungBeom Kimf77a2a92012-07-20 16:44:11 +090093 void *planes[CSC_MAX_PLANES];
Jiho Chang47bd9532012-03-24 05:56:11 +090094} CSC_BUFFER;
95
Jiho Chang3b540842012-04-26 13:39:20 -070096typedef struct _CSC_HW_PROPERTY {
97 int fixed_node;
98 int mode_drm;
99} CSC_HW_PROPERTY;
100
Jiho Chang47bd9532012-03-24 05:56:11 +0900101typedef 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;
Jiho Chang3b540842012-04-26 13:39:20 -0700109 CSC_HW_PROPERTY hw_property;
Jiho Chang47bd9532012-03-24 05:56:11 +0900110} CSC_HANDLE;
111
Jiho Chang47bd9532012-03-24 05:56:11 +0900112/* source is RGB888 */
113static 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 */
147static 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 */
189static 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 */
227static 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
261static 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;
Greg Hackmannae570c52013-01-03 11:22:37 -0800276 case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
Jiho Chang47bd9532012-03-24 05:56:11 +0900277 ret = conv_sw_src_argb888(handle);
278 break;
279 default:
280 ret = CSC_ErrorUnsupportFormat;
281 break;
282 }
283
284 return ret;
285}
286
287static CSC_ERRORCODE conv_hw(
288 CSC_HANDLE *handle)
289{
290 CSC_ERRORCODE ret = CSC_ErrorNone;
Jiho Chang47bd9532012-03-24 05:56:11 +0900291 switch (handle->csc_hw_type) {
Jiho Chang3b540842012-04-26 13:39:20 -0700292#ifdef ENABLE_FIMC
Jiho Chang47bd9532012-03-24 05:56:11 +0900293 case CSC_HW_TYPE_FIMC:
294 {
295 void *src_addr[3];
296 void *dst_addr[3];
Jiho Chang3b540842012-04-26 13:39:20 -0700297 OMX_COLOR_FORMATTYPE src_omx_format;
298 OMX_COLOR_FORMATTYPE dst_omx_format;
Jiho Chang47bd9532012-03-24 05:56:11 +0900299 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];
Jiho Chang3b540842012-04-26 13:39:20 -0700304 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);
Jiho Chang47bd9532012-03-24 05:56:11 +0900306 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,
Jiho Chang3b540842012-04-26 13:39:20 -0700312 dst_omx_format,
313 src_omx_format);
Jiho Chang47bd9532012-03-24 05:56:11 +0900314 break;
315 }
316#endif
Jiho Chang3b540842012-04-26 13:39:20 -0700317#ifdef ENABLE_GSCALER
Jiho Chang47bd9532012-03-24 05:56:11 +0900318 case CSC_HW_TYPE_GSCALER:
Jiho Chang3b540842012-04-26 13:39:20 -0700319 if (exynos_gsc_convert(handle->csc_hw_handle) != 0) {
320 ALOGE("%s:: exynos_gsc_convert() fail", __func__);
321 ret = CSC_Error;
322 }
Jiho Chang47bd9532012-03-24 05:56:11 +0900323 break;
324#endif
Greg Hackmann8f10f922013-01-14 15:54:46 -0800325#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
Jiho Chang47bd9532012-03-24 05:56:11 +0900348 default:
Jiho Chang3b540842012-04-26 13:39:20 -0700349 ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type);
350 ret = CSC_ErrorNotImplemented;
Jiho Chang47bd9532012-03-24 05:56:11 +0900351 break;
352 }
353
Jiho Chang3b540842012-04-26 13:39:20 -0700354 return ret;
Jiho Chang47bd9532012-03-24 05:56:11 +0900355}
356
Jiho Chang3b540842012-04-26 13:39:20 -0700357static CSC_ERRORCODE csc_init_hw(
358 void *handle)
Jiho Chang47bd9532012-03-24 05:56:11 +0900359{
360 CSC_HANDLE *csc_handle;
Jiho Chang3b540842012-04-26 13:39:20 -0700361 CSC_ERRORCODE ret = CSC_ErrorNone;
Jiho Chang47bd9532012-03-24 05:56:11 +0900362
Jiho Chang3b540842012-04-26 13:39:20 -0700363 csc_handle = (CSC_HANDLE *)handle;
364 if (csc_handle->csc_method == CSC_METHOD_HW) {
Jiho Chang47bd9532012-03-24 05:56:11 +0900365 switch (csc_handle->csc_hw_type) {
Jiho Chang3b540842012-04-26 13:39:20 -0700366#ifdef ENABLE_FIMC
Jiho Chang47bd9532012-03-24 05:56:11 +0900367 case CSC_HW_TYPE_FIMC:
368 csc_handle->csc_hw_handle = csc_hwconverter_open();
Jiho Chang3b540842012-04-26 13:39:20 -0700369 ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__);
Jiho Chang47bd9532012-03-24 05:56:11 +0900370 break;
371#endif
Jiho Chang3b540842012-04-26 13:39:20 -0700372#ifdef ENABLE_GSCALER
Jiho Chang47bd9532012-03-24 05:56:11 +0900373 case CSC_HW_TYPE_GSCALER:
Jiho Chang3b540842012-04-26 13:39:20 -0700374 if (csc_handle->hw_property.fixed_node >= 0)
Dima Zavin33aa35f2012-10-05 16:04:52 -0700375 csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0);
Jiho Chang3b540842012-04-26 13:39:20 -0700376 else
Jiho Chang47bd9532012-03-24 05:56:11 +0900377 csc_handle->csc_hw_handle = exynos_gsc_create();
Jiho Chang3b540842012-04-26 13:39:20 -0700378 ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__);
Jiho Chang47bd9532012-03-24 05:56:11 +0900379 break;
380#endif
Greg Hackmann8f10f922013-01-14 15:54:46 -0800381#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
Jiho Chang47bd9532012-03-24 05:56:11 +0900399 default:
Dima Zavinbaa53d42012-04-02 23:44:05 -0700400 ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__);
Greg Hackmann8f10f922013-01-14 15:54:46 -0800401 csc_handle->csc_hw_handle = NULL;
Jiho Chang47bd9532012-03-24 05:56:11 +0900402 break;
403 }
404 }
405
Jiho Chang47bd9532012-03-24 05:56:11 +0900406 if (csc_handle->csc_method == CSC_METHOD_HW) {
407 if (csc_handle->csc_hw_handle == NULL) {
Dima Zavinbaa53d42012-04-02 23:44:05 -0700408 ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__);
Greg Hackmann4328d392012-12-10 15:28:45 -0800409 ret = CSC_Error;
Jiho Chang47bd9532012-03-24 05:56:11 +0900410 }
411 }
412
Jiho Chang3b540842012-04-26 13:39:20 -0700413 ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method);
414
415 return ret;
416}
417
418static 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,
Jiho Changd50f6502012-06-01 20:40:47 +0000440 csc_handle->src_format.crop_width,
441 csc_handle->src_format.crop_height,
Jiho Chang3b540842012-04-26 13:39:20 -0700442 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,
Jiho Changd50f6502012-06-01 20:40:47 +0000452 csc_handle->dst_format.crop_width,
453 csc_handle->dst_format.crop_height,
Jiho Chang3b540842012-04-26 13:39:20 -0700454 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
455 csc_handle->dst_format.cacheable,
Greg Hackmannbcd3f112012-10-11 14:22:43 -0700456 csc_handle->hw_property.mode_drm,
457 0);
Jiho Chang3b540842012-04-26 13:39:20 -0700458 break;
459#endif
Greg Hackmann8f10f922013-01-14 15:54:46 -0800460#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
Jiho Chang3b540842012-04-26 13:39:20 -0700496 default:
497 ALOGE("%s:: unsupported csc_hw_type", __func__);
498 break;
499 }
500 }
501
502 return ret;
503}
504
505static CSC_ERRORCODE csc_set_buffer(
506 void *handle)
507{
508 CSC_HANDLE *csc_handle;
509 CSC_ERRORCODE ret = CSC_ErrorNone;
Jiho Chang3b540842012-04-26 13:39:20 -0700510
511 if (handle == NULL)
512 return CSC_ErrorNotInit;
513
514 csc_handle = (CSC_HANDLE *)handle;
515 if (csc_handle->csc_method == CSC_METHOD_HW) {
Jiho Chang3b540842012-04-26 13:39:20 -0700516 switch (csc_handle->csc_hw_type) {
517 case CSC_HW_TYPE_FIMC:
518 break;
519#ifdef ENABLE_GSCALER
520 case CSC_HW_TYPE_GSCALER:
Benoit Goby9f6d8282012-10-04 13:25:29 -0700521 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);
Jiho Chang3b540842012-04-26 13:39:20 -0700523 break;
524#endif
Greg Hackmann8f10f922013-01-14 15:54:46 -0800525#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
Jiho Chang3b540842012-04-26 13:39:20 -0700541 default:
542 ALOGE("%s:: unsupported csc_hw_type", __func__);
543 break;
544 }
545 }
546
547 return ret;
548}
549
550void *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;
Jiho Chang47bd9532012-03-24 05:56:11 +0900562
563 return (void *)csc_handle;
564}
565
566CSC_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;
Greg Hackmann4f74fda2013-01-08 12:30:39 -0800573 if (csc_handle->csc_hw_handle) {
Jiho Chang47bd9532012-03-24 05:56:11 +0900574 switch (csc_handle->csc_hw_type) {
Jiho Chang3b540842012-04-26 13:39:20 -0700575#ifdef ENABLE_FIMC
Jiho Chang47bd9532012-03-24 05:56:11 +0900576 case CSC_HW_TYPE_FIMC:
577 csc_hwconverter_close(csc_handle->csc_hw_handle);
578 break;
579#endif
Jiho Chang3b540842012-04-26 13:39:20 -0700580#ifdef ENABLE_GSCALER
Jiho Chang47bd9532012-03-24 05:56:11 +0900581 case CSC_HW_TYPE_GSCALER:
582 exynos_gsc_destroy(csc_handle->csc_hw_handle);
583 break;
584#endif
Greg Hackmann8f10f922013-01-14 15:54:46 -0800585#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
Jiho Chang47bd9532012-03-24 05:56:11 +0900594 default:
Dima Zavinbaa53d42012-04-02 23:44:05 -0700595 ALOGE("%s:: unsupported csc_hw_type", __func__);
Jiho Chang47bd9532012-03-24 05:56:11 +0900596 break;
597 }
598 }
599
600 if (csc_handle != NULL) {
601 free(csc_handle);
602 ret = CSC_ErrorNone;
603 }
604
605 return ret;
606}
607
608CSC_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
Greg Hackmann4f74fda2013-01-08 12:30:39 -0800624CSC_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
Jiho Chang3b540842012-04-26 13:39:20 -0700640CSC_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;
Greg Hackmannc3fb36e2013-01-14 15:30:24 -0800652
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
Jiho Chang3b540842012-04-26 13:39:20 -0700658 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;
Greg Hackmannc3fb36e2013-01-14 15:30:24 -0800665 case CSC_HW_PROPERTY_HW_TYPE:
666 csc_handle->csc_hw_type = value;
667 break;
Jiho Chang3b540842012-04-26 13:39:20 -0700668 default:
669 ALOGE("%s:: not supported hw property", __func__);
670 ret = CSC_ErrorUnsupportFormat;
671 }
672
673 return ret;
674}
675
Jiho Chang47bd9532012-03-24 05:56:11 +0900676CSC_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
706CSC_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
Jiho Chang47bd9532012-03-24 05:56:11 +0900733 return ret;
734}
735
736CSC_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
766CSC_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
Jiho Chang47bd9532012-03-24 05:56:11 +0900793 return ret;
794}
795
796CSC_ERRORCODE csc_set_src_buffer(
SeungBeom Kimf77a2a92012-07-20 16:44:11 +0900797 void *handle,
798 void *addr[3])
Jiho Chang47bd9532012-03-24 05:56:11 +0900799{
800 CSC_HANDLE *csc_handle;
801 CSC_ERRORCODE ret = CSC_ErrorNone;
Jiho Chang47bd9532012-03-24 05:56:11 +0900802
803 if (handle == NULL)
804 return CSC_ErrorNotInit;
805
806 csc_handle = (CSC_HANDLE *)handle;
SeungBeom Kimf77a2a92012-07-20 16:44:11 +0900807 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];
Jiho Chang47bd9532012-03-24 05:56:11 +0900810
Jiho Chang47bd9532012-03-24 05:56:11 +0900811 return ret;
812}
813
814CSC_ERRORCODE csc_set_dst_buffer(
SeungBeom Kimf77a2a92012-07-20 16:44:11 +0900815 void *handle,
816 void *addr[3])
Jiho Chang47bd9532012-03-24 05:56:11 +0900817{
818 CSC_HANDLE *csc_handle;
819 CSC_ERRORCODE ret = CSC_ErrorNone;
Jiho Chang47bd9532012-03-24 05:56:11 +0900820
821 if (handle == NULL)
822 return CSC_ErrorNotInit;
823
824 csc_handle = (CSC_HANDLE *)handle;
SeungBeom Kimf77a2a92012-07-20 16:44:11 +0900825 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];
Jiho Chang47bd9532012-03-24 05:56:11 +0900828
Jiho Chang47bd9532012-03-24 05:56:11 +0900829 return ret;
830}
831
832CSC_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
Jiho Chang3b540842012-04-26 13:39:20 -0700841 if ((csc_handle->csc_method == CSC_METHOD_HW) &&
Greg Hackmann4328d392012-12-10 15:28:45 -0800842 (csc_handle->csc_hw_handle == NULL)) {
843 ret = csc_init_hw(handle);
844 if (ret != CSC_ErrorNone)
845 return ret;
846 }
Jiho Chang3b540842012-04-26 13:39:20 -0700847
Greg Hackmann4328d392012-12-10 15:28:45 -0800848 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;
Jiho Chang3b540842012-04-26 13:39:20 -0700855
Jiho Chang47bd9532012-03-24 05:56:11 +0900856 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}