Commit | Line | Data |
---|---|---|
47bd9530 JC |
1 | /* |
2 | * | |
3 | * Copyright 2012 Samsung Electronics S.LSI Co. LTD | |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * @file csc.c | |
20 | * | |
21 | * @brief color space convertion abstract source | |
22 | * | |
23 | * @author Pyoungjae Jung(pjet.jung@samsung.com) | |
24 | * | |
25 | * @version 1.0.0 | |
26 | * | |
27 | * @history | |
28 | * 2012.1.11 : Create | |
29 | */ | |
30 | #define LOG_TAG "libcsc" | |
31 | #include <cutils/log.h> | |
bb99f0ed | 32 | #include <errno.h> |
47bd9530 | 33 | |
cbb59e66 | 34 | #include <errno.h> |
47bd9530 JC |
35 | #include <stdio.h> |
36 | #include <stdlib.h> | |
37 | #include <utils/Log.h> | |
3b540849 | 38 | #include <system/graphics.h> |
47bd9530 JC |
39 | |
40 | #include "csc.h" | |
41 | #include "exynos_format.h" | |
42 | #include "swconverter.h" | |
43 | ||
44 | #ifdef EXYNOS_OMX | |
45 | #include "Exynos_OMX_Def.h" | |
46 | #else | |
47 | #include "SEC_OMX_Def.h" | |
48 | #endif | |
49 | ||
3b540849 | 50 | #ifdef ENABLE_FIMC |
47bd9530 JC |
51 | #include "hwconverter_wrapper.h" |
52 | #endif | |
53 | ||
3b540849 | 54 | #ifdef ENABLE_GSCALER |
47bd9530 JC |
55 | #include "exynos_gscaler.h" |
56 | #endif | |
57 | ||
8f10f92b GH |
58 | #ifdef ENABLE_G2D |
59 | #include <fcntl.h> | |
60 | #include <sys/ioctl.h> | |
61 | #include "fimg2d.h" | |
62 | ||
63 | typedef struct | |
64 | { | |
65 | struct fimg2d_image src; | |
66 | struct fimg2d_image dst; | |
67 | int fd; | |
68 | } g2d_data; | |
69 | #endif | |
70 | ||
47bd9530 | 71 | #define GSCALER_IMG_ALIGN 16 |
47bd9530 JC |
72 | #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) |
73 | ||
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 | ||
47bd9530 JC |
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; | |
3b540849 | 91 | unsigned int mode_drm; |
47bd9530 JC |
92 | } CSC_FORMAT; |
93 | ||
94 | typedef struct _CSC_BUFFER { | |
f77a2a9d | 95 | void *planes[CSC_MAX_PLANES]; |
47bd9530 JC |
96 | } CSC_BUFFER; |
97 | ||
3b540849 JC |
98 | typedef struct _CSC_HW_PROPERTY { |
99 | int fixed_node; | |
100 | int mode_drm; | |
101 | } CSC_HW_PROPERTY; | |
102 | ||
47bd9530 JC |
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; | |
3b540849 | 111 | CSC_HW_PROPERTY hw_property; |
47bd9530 JC |
112 | } CSC_HANDLE; |
113 | ||
47bd9530 JC |
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; | |
ae570c5d | 278 | case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888: |
47bd9530 JC |
279 | ret = conv_sw_src_argb888(handle); |
280 | break; | |
281 | default: | |
282 | ret = CSC_ErrorUnsupportFormat; | |
283 | break; | |
284 | } | |
285 | ||
286 | return ret; | |
287 | } | |
288 | ||
289 | static CSC_ERRORCODE conv_hw( | |
290 | CSC_HANDLE *handle) | |
291 | { | |
292 | CSC_ERRORCODE ret = CSC_ErrorNone; | |
47bd9530 | 293 | switch (handle->csc_hw_type) { |
3b540849 | 294 | #ifdef ENABLE_FIMC |
47bd9530 JC |
295 | case CSC_HW_TYPE_FIMC: |
296 | { | |
297 | void *src_addr[3]; | |
298 | void *dst_addr[3]; | |
3b540849 JC |
299 | OMX_COLOR_FORMATTYPE src_omx_format; |
300 | OMX_COLOR_FORMATTYPE dst_omx_format; | |
47bd9530 JC |
301 | src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE]; |
302 | src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE]; | |
303 | dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE]; | |
304 | dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE]; | |
305 | dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE]; | |
3b540849 JC |
306 | src_omx_format = hal_2_omx_pixel_format(handle->src_format.color_format); |
307 | dst_omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format); | |
47bd9530 JC |
308 | csc_hwconverter_convert_nv12t( |
309 | handle->csc_hw_handle, | |
310 | dst_addr, | |
311 | src_addr, | |
312 | handle->dst_format.width, | |
313 | handle->dst_format.height, | |
3b540849 JC |
314 | dst_omx_format, |
315 | src_omx_format); | |
47bd9530 JC |
316 | break; |
317 | } | |
318 | #endif | |
3b540849 | 319 | #ifdef ENABLE_GSCALER |
47bd9530 | 320 | case CSC_HW_TYPE_GSCALER: |
3b540849 JC |
321 | if (exynos_gsc_convert(handle->csc_hw_handle) != 0) { |
322 | ALOGE("%s:: exynos_gsc_convert() fail", __func__); | |
323 | ret = CSC_Error; | |
324 | } | |
47bd9530 | 325 | break; |
8f10f92b GH |
326 | #endif |
327 | #ifdef ENABLE_G2D | |
328 | case CSC_HW_TYPE_G2D: | |
329 | { | |
330 | g2d_data *g2d = (g2d_data *)handle->csc_hw_handle; | |
331 | struct fimg2d_blit blit; | |
332 | int err; | |
333 | ||
334 | memset(&blit, 0, sizeof(blit)); | |
335 | blit.op = BLIT_OP_SRC_COPY; | |
336 | blit.param.g_alpha = 0xFF; | |
337 | blit.src = &g2d->src; | |
338 | blit.dst = &g2d->dst; | |
339 | blit.sync = BLIT_SYNC; | |
340 | ||
341 | err = ioctl(g2d->fd, FIMG2D_BITBLT_BLIT, &blit); | |
342 | if (err < 0) { | |
343 | ALOGE("FIMG2D_BITBLT_BLIT ioctl failed: %s", strerror(errno)); | |
344 | ret = CSC_Error; | |
345 | } | |
346 | ||
347 | break; | |
348 | } | |
47bd9530 JC |
349 | #endif |
350 | default: | |
3b540849 JC |
351 | ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type); |
352 | ret = CSC_ErrorNotImplemented; | |
47bd9530 JC |
353 | break; |
354 | } | |
355 | ||
3b540849 | 356 | return ret; |
47bd9530 JC |
357 | } |
358 | ||
3b540849 JC |
359 | static CSC_ERRORCODE csc_init_hw( |
360 | void *handle) | |
47bd9530 JC |
361 | { |
362 | CSC_HANDLE *csc_handle; | |
3b540849 | 363 | CSC_ERRORCODE ret = CSC_ErrorNone; |
47bd9530 | 364 | |
3b540849 JC |
365 | csc_handle = (CSC_HANDLE *)handle; |
366 | if (csc_handle->csc_method == CSC_METHOD_HW) { | |
47bd9530 | 367 | switch (csc_handle->csc_hw_type) { |
3b540849 | 368 | #ifdef ENABLE_FIMC |
47bd9530 JC |
369 | case CSC_HW_TYPE_FIMC: |
370 | csc_handle->csc_hw_handle = csc_hwconverter_open(); | |
3b540849 | 371 | ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__); |
47bd9530 JC |
372 | break; |
373 | #endif | |
3b540849 | 374 | #ifdef ENABLE_GSCALER |
47bd9530 | 375 | case CSC_HW_TYPE_GSCALER: |
3b540849 | 376 | if (csc_handle->hw_property.fixed_node >= 0) |
33aa35f1 | 377 | csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0); |
3b540849 | 378 | else |
47bd9530 | 379 | csc_handle->csc_hw_handle = exynos_gsc_create(); |
3b540849 | 380 | ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__); |
47bd9530 | 381 | break; |
8f10f92b GH |
382 | #endif |
383 | #ifdef ENABLE_G2D | |
384 | case CSC_HW_TYPE_G2D: | |
385 | { | |
386 | g2d_data *g2d = calloc(1, sizeof(g2d_data)); | |
387 | if (!g2d) { | |
388 | ALOGE("failed to allocate G2D data"); | |
389 | break; | |
390 | } | |
391 | g2d->fd = open("/dev/fimg2d", O_RDWR); | |
392 | if (g2d->fd < 0) { | |
393 | ALOGE("failed to open G2D: %s", strerror(errno)); | |
394 | free(g2d); | |
395 | } else { | |
396 | csc_handle->csc_hw_handle = g2d; | |
397 | } | |
398 | break; | |
399 | } | |
47bd9530 JC |
400 | #endif |
401 | default: | |
baa53d4c | 402 | ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__); |
8f10f92b | 403 | csc_handle->csc_hw_handle = NULL; |
47bd9530 JC |
404 | break; |
405 | } | |
406 | } | |
407 | ||
47bd9530 JC |
408 | if (csc_handle->csc_method == CSC_METHOD_HW) { |
409 | if (csc_handle->csc_hw_handle == NULL) { | |
baa53d4c | 410 | ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__); |
4328d394 | 411 | ret = CSC_Error; |
47bd9530 JC |
412 | } |
413 | } | |
414 | ||
3b540849 JC |
415 | ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method); |
416 | ||
417 | return ret; | |
418 | } | |
419 | ||
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, | |
d50f650b JC |
442 | csc_handle->src_format.crop_width, |
443 | csc_handle->src_format.crop_height, | |
3b540849 JC |
444 | HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format), |
445 | csc_handle->src_format.cacheable, | |
446 | csc_handle->hw_property.mode_drm); | |
447 | ||
448 | exynos_gsc_set_dst_format( | |
449 | csc_handle->csc_hw_handle, | |
450 | ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN), | |
451 | ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN), | |
452 | csc_handle->dst_format.crop_left, | |
453 | csc_handle->dst_format.crop_top, | |
d50f650b JC |
454 | csc_handle->dst_format.crop_width, |
455 | csc_handle->dst_format.crop_height, | |
3b540849 JC |
456 | HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format), |
457 | csc_handle->dst_format.cacheable, | |
bcd3f11d GH |
458 | csc_handle->hw_property.mode_drm, |
459 | 0); | |
3b540849 | 460 | break; |
8f10f92b GH |
461 | #endif |
462 | #ifdef ENABLE_G2D | |
463 | case CSC_HW_TYPE_G2D: | |
464 | { | |
465 | g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; | |
466 | ||
467 | g2d->src.width = ALIGN(csc_handle->src_format.width, | |
468 | GSCALER_IMG_ALIGN); | |
469 | g2d->src.height = csc_handle->src_format.height; | |
470 | g2d->src.stride = g2d->src.width * | |
471 | hal_2_g2d_bpp(csc_handle->src_format.color_format) >> 3; | |
472 | g2d->src.order = hal_2_g2d_pixel_order(csc_handle->src_format.color_format); | |
473 | g2d->src.fmt = hal_2_g2d_color_format(csc_handle->src_format.color_format); | |
474 | g2d->src.rect.x1 = csc_handle->src_format.crop_left; | |
475 | g2d->src.rect.y1 = csc_handle->src_format.crop_top; | |
476 | g2d->src.rect.x2 = csc_handle->src_format.crop_left + | |
477 | csc_handle->src_format.crop_width; | |
478 | g2d->src.rect.y2 = csc_handle->src_format.crop_top + | |
479 | csc_handle->src_format.crop_height; | |
480 | ||
481 | g2d->dst.width = ALIGN(csc_handle->dst_format.width, | |
482 | GSCALER_IMG_ALIGN); | |
483 | g2d->dst.height = csc_handle->dst_format.height; | |
484 | g2d->dst.stride = g2d->dst.width * | |
485 | hal_2_g2d_bpp(csc_handle->dst_format.color_format) >> 3; | |
486 | g2d->dst.order = hal_2_g2d_pixel_order(csc_handle->dst_format.color_format); | |
487 | g2d->dst.fmt = hal_2_g2d_color_format(csc_handle->dst_format.color_format); | |
488 | g2d->dst.rect.x1 = csc_handle->dst_format.crop_left; | |
489 | g2d->dst.rect.y1 = csc_handle->dst_format.crop_top; | |
490 | g2d->dst.rect.x2 = csc_handle->dst_format.crop_left + | |
491 | csc_handle->dst_format.crop_width; | |
492 | g2d->dst.rect.y2 = csc_handle->dst_format.crop_top + | |
493 | csc_handle->dst_format.crop_height; | |
494 | ||
495 | break; | |
496 | } | |
3b540849 JC |
497 | #endif |
498 | default: | |
499 | ALOGE("%s:: unsupported csc_hw_type", __func__); | |
500 | break; | |
501 | } | |
502 | } | |
503 | ||
504 | return ret; | |
505 | } | |
506 | ||
507 | static CSC_ERRORCODE csc_set_buffer( | |
508 | void *handle) | |
509 | { | |
510 | CSC_HANDLE *csc_handle; | |
511 | CSC_ERRORCODE ret = CSC_ErrorNone; | |
3b540849 JC |
512 | |
513 | if (handle == NULL) | |
514 | return CSC_ErrorNotInit; | |
515 | ||
516 | csc_handle = (CSC_HANDLE *)handle; | |
517 | if (csc_handle->csc_method == CSC_METHOD_HW) { | |
3b540849 JC |
518 | switch (csc_handle->csc_hw_type) { |
519 | case CSC_HW_TYPE_FIMC: | |
520 | break; | |
521 | #ifdef ENABLE_GSCALER | |
522 | case CSC_HW_TYPE_GSCALER: | |
9f6d8287 BG |
523 | exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1); |
524 | exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1); | |
3b540849 | 525 | break; |
8f10f92b GH |
526 | #endif |
527 | #ifdef ENABLE_G2D | |
528 | case CSC_HW_TYPE_G2D: | |
529 | { | |
530 | g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; | |
531 | ||
532 | g2d->src.addr.type = ADDR_DMA_BUF; | |
533 | g2d->src.addr.fd[0] = (int)csc_handle->src_buffer.planes[0]; | |
534 | g2d->src.addr.fd[1] = (int)csc_handle->src_buffer.planes[1]; | |
535 | ||
536 | g2d->dst.addr.type = ADDR_DMA_BUF; | |
537 | g2d->dst.addr.fd[0] = (int)csc_handle->dst_buffer.planes[0]; | |
538 | g2d->dst.addr.fd[1] = (int)csc_handle->dst_buffer.planes[1]; | |
539 | ||
540 | break; | |
541 | } | |
3b540849 JC |
542 | #endif |
543 | default: | |
544 | ALOGE("%s:: unsupported csc_hw_type", __func__); | |
545 | break; | |
546 | } | |
547 | } | |
548 | ||
549 | return ret; | |
550 | } | |
551 | ||
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; | |
47bd9530 JC |
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; | |
4f74fdad | 575 | if (csc_handle->csc_hw_handle) { |
47bd9530 | 576 | switch (csc_handle->csc_hw_type) { |
3b540849 | 577 | #ifdef ENABLE_FIMC |
47bd9530 JC |
578 | case CSC_HW_TYPE_FIMC: |
579 | csc_hwconverter_close(csc_handle->csc_hw_handle); | |
580 | break; | |
581 | #endif | |
3b540849 | 582 | #ifdef ENABLE_GSCALER |
47bd9530 JC |
583 | case CSC_HW_TYPE_GSCALER: |
584 | exynos_gsc_destroy(csc_handle->csc_hw_handle); | |
585 | break; | |
8f10f92b GH |
586 | #endif |
587 | #ifdef ENABLE_G2D | |
588 | case CSC_HW_TYPE_G2D: | |
589 | { | |
590 | g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; | |
591 | close(g2d->fd); | |
592 | free(g2d); | |
593 | break; | |
594 | } | |
47bd9530 JC |
595 | #endif |
596 | default: | |
baa53d4c | 597 | ALOGE("%s:: unsupported csc_hw_type", __func__); |
47bd9530 JC |
598 | break; |
599 | } | |
600 | } | |
601 | ||
602 | if (csc_handle != NULL) { | |
603 | free(csc_handle); | |
604 | ret = CSC_ErrorNone; | |
605 | } | |
606 | ||
607 | return ret; | |
608 | } | |
609 | ||
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 | ||
4f74fdad GH |
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 | ||
3b540849 JC |
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; | |
c3fb36ed GH |
654 | |
655 | if (csc_handle->csc_hw_handle) { | |
656 | ALOGE("%s:: cannot set hw property after hw is already initialized", __func__); | |
657 | return CSC_ErrorUnsupportFormat; | |
658 | } | |
659 | ||
3b540849 JC |
660 | switch (property) { |
661 | case CSC_HW_PROPERTY_FIXED_NODE: | |
662 | csc_handle->hw_property.fixed_node = value; | |
663 | break; | |
664 | case CSC_HW_PROPERTY_MODE_DRM: | |
665 | csc_handle->hw_property.mode_drm = value; | |
666 | break; | |
c3fb36ed GH |
667 | case CSC_HW_PROPERTY_HW_TYPE: |
668 | csc_handle->csc_hw_type = value; | |
669 | break; | |
3b540849 JC |
670 | default: |
671 | ALOGE("%s:: not supported hw property", __func__); | |
672 | ret = CSC_ErrorUnsupportFormat; | |
673 | } | |
674 | ||
675 | return ret; | |
676 | } | |
677 | ||
47bd9530 JC |
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 | ||
47bd9530 JC |
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 | ||
47bd9530 JC |
795 | return ret; |
796 | } | |
797 | ||
798 | CSC_ERRORCODE csc_set_src_buffer( | |
f77a2a9d SK |
799 | void *handle, |
800 | void *addr[3]) | |
47bd9530 JC |
801 | { |
802 | CSC_HANDLE *csc_handle; | |
803 | CSC_ERRORCODE ret = CSC_ErrorNone; | |
47bd9530 JC |
804 | |
805 | if (handle == NULL) | |
806 | return CSC_ErrorNotInit; | |
807 | ||
808 | csc_handle = (CSC_HANDLE *)handle; | |
f77a2a9d SK |
809 | csc_handle->src_buffer.planes[CSC_Y_PLANE] = addr[0]; |
810 | csc_handle->src_buffer.planes[CSC_U_PLANE] = addr[1]; | |
811 | csc_handle->src_buffer.planes[CSC_V_PLANE] = addr[2]; | |
47bd9530 | 812 | |
47bd9530 JC |
813 | return ret; |
814 | } | |
815 | ||
816 | CSC_ERRORCODE csc_set_dst_buffer( | |
f77a2a9d SK |
817 | void *handle, |
818 | void *addr[3]) | |
47bd9530 JC |
819 | { |
820 | CSC_HANDLE *csc_handle; | |
821 | CSC_ERRORCODE ret = CSC_ErrorNone; | |
47bd9530 JC |
822 | |
823 | if (handle == NULL) | |
824 | return CSC_ErrorNotInit; | |
825 | ||
826 | csc_handle = (CSC_HANDLE *)handle; | |
f77a2a9d SK |
827 | csc_handle->dst_buffer.planes[CSC_Y_PLANE] = addr[0]; |
828 | csc_handle->dst_buffer.planes[CSC_U_PLANE] = addr[1]; | |
829 | csc_handle->dst_buffer.planes[CSC_V_PLANE] = addr[2]; | |
47bd9530 | 830 | |
47bd9530 JC |
831 | return ret; |
832 | } | |
833 | ||
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 | ||
3b540849 | 843 | if ((csc_handle->csc_method == CSC_METHOD_HW) && |
4328d394 GH |
844 | (csc_handle->csc_hw_handle == NULL)) { |
845 | ret = csc_init_hw(handle); | |
846 | if (ret != CSC_ErrorNone) | |
847 | return ret; | |
848 | } | |
849 | ||
850 | ret = csc_set_format(csc_handle); | |
851 | if (ret != CSC_ErrorNone) | |
852 | return ret; | |
3b540849 | 853 | |
4328d394 GH |
854 | ret = csc_set_buffer(csc_handle); |
855 | if (ret != CSC_ErrorNone) | |
856 | return ret; | |
3b540849 | 857 | |
47bd9530 JC |
858 | if (csc_handle->csc_method == CSC_METHOD_HW) |
859 | ret = conv_hw(csc_handle); | |
860 | else | |
861 | ret = conv_sw(csc_handle); | |
862 | ||
863 | return ret; | |
864 | } |