Fix build after C++11 migration.
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libgscaler / exynos_gscaler.c
CommitLineData
70007c4e
JC
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright@ Samsung Electronics 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 exynos_gscaler.c
20 * \brief header file for Gscaler HAL
21 * \author ShinWon Lee (shinwon.lee@samsung.com)
22 * \date 2012/01/09
23 *
24 * <b>Revision History: </b>
25 * - 2012.01.09 : ShinWon Lee(shinwon.lee@samsung.com) \n
26 * Create
27 *
28 * - 2012.02.07 : ShinWon Lee(shinwon.lee@samsung.com) \n
29 * Change file name to exynos_gscaler.h
30 *
31 * - 2012.02.09 : Sangwoo, Parkk(sw5771.park@samsung.com) \n
32 * Use Multiple Gscaler by Multiple Process
33 *
34 * - 2012.02.20 : Sangwoo, Park(sw5771.park@samsung.com) \n
35 * Add exynos_gsc_set_rotation() API
36 *
37 * - 2012.02.20 : ShinWon Lee(shinwon.lee@samsung.com) \n
38 * Add size constrain
39 *
40 */
41
42//#define LOG_NDEBUG 0
43#include "exynos_gsc_utils.h"
33aa35f1 44#include "content_protect.h"
70007c4e 45
9f6d8287 46static int exynos_gsc_m2m_wait_frame_done(void *handle);
33aa35f1 47static int exynos_gsc_m2m_stop(void *handle);
9f6d8287 48
70007c4e
JC
49static unsigned int m_gsc_get_plane_count(
50 int v4l_pixel_format)
51{
52 int plane_count = 0;
53
54 switch (v4l_pixel_format) {
55 case V4L2_PIX_FMT_RGB32:
56 case V4L2_PIX_FMT_BGR32:
57 case V4L2_PIX_FMT_RGB24:
58 case V4L2_PIX_FMT_RGB565:
59 case V4L2_PIX_FMT_RGB555X:
60 case V4L2_PIX_FMT_RGB444:
61 case V4L2_PIX_FMT_YUYV:
62 case V4L2_PIX_FMT_UYVY:
23dac69c
SK
63 case V4L2_PIX_FMT_NV16:
64 case V4L2_PIX_FMT_NV61:
70007c4e
JC
65 plane_count = 1;
66 break;
67 case V4L2_PIX_FMT_NV12M:
68 case V4L2_PIX_FMT_NV12MT_16X16:
2607aa30 69 case V4L2_PIX_FMT_NV12:
70007c4e 70 case V4L2_PIX_FMT_NV21:
66e91991 71 case V4L2_PIX_FMT_NV21M:
70007c4e
JC
72 plane_count = 2;
73 break;
74 case V4L2_PIX_FMT_YVU420M:
75 case V4L2_PIX_FMT_YUV422P:
4006f615 76 case V4L2_PIX_FMT_YUV420M:
70007c4e
JC
77 plane_count = 3;
78 break;
79 default:
6134b8bb 80 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
70007c4e
JC
81 __func__, v4l_pixel_format);
82 plane_count = -1;
83 break;
84 }
85
86 return plane_count;
87}
88
89static unsigned int m_gsc_get_plane_size(
90 unsigned int *plane_size,
91 unsigned int width,
92 unsigned int height,
93 int v4l_pixel_format)
94{
95 switch (v4l_pixel_format) {
96 /* 1 plane */
97 case V4L2_PIX_FMT_RGB32:
98 case V4L2_PIX_FMT_BGR32:
99 plane_size[0] = width * height * 4;
100 plane_size[1] = 0;
101 plane_size[2] = 0;
102 break;
103 case V4L2_PIX_FMT_RGB24:
104 plane_size[0] = width * height * 3;
105 plane_size[1] = 0;
106 plane_size[2] = 0;
107 break;
108 case V4L2_PIX_FMT_RGB565:
109 case V4L2_PIX_FMT_RGB555X:
110 case V4L2_PIX_FMT_RGB444:
111 case V4L2_PIX_FMT_YUYV:
112 case V4L2_PIX_FMT_UYVY:
113 plane_size[0] = width * height * 2;
114 plane_size[1] = 0;
115 plane_size[2] = 0;
116 break;
117 /* 2 planes */
118 case V4L2_PIX_FMT_NV12M:
2607aa30 119 case V4L2_PIX_FMT_NV12:
70007c4e 120 case V4L2_PIX_FMT_NV21:
66e91991 121 case V4L2_PIX_FMT_NV21M:
e6a0625b
JC
122 plane_size[0] = width * height;
123 plane_size[1] = width * (height / 2);
124 plane_size[2] = 0;
125 break;
70007c4e
JC
126 case V4L2_PIX_FMT_NV16:
127 case V4L2_PIX_FMT_NV61:
35b3cc21
JS
128 plane_size[0] = width * height * 2;
129 plane_size[1] = 0;
70007c4e
JC
130 plane_size[2] = 0;
131 break;
132 case V4L2_PIX_FMT_NV12MT_16X16:
133 plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
134 plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
135 plane_size[2] = 0;
136 break;
137 /* 3 planes */
138 case V4L2_PIX_FMT_YVU420M:
139 case V4L2_PIX_FMT_YUV422P:
140 plane_size[0] = width * height;
141 plane_size[1] = (width / 2) * (height / 2);
142 plane_size[2] = (width / 2) * (height / 2);
143 break;
144 default:
6134b8bb 145 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
70007c4e
JC
146 __func__, v4l_pixel_format);
147 return -1;
148 break;
149 }
150
151 return 0;
152}
153
e76fa944
RSZ
154static int m_exynos_gsc_multiple_of_n(
155 int number, int N)
156{
157 int result = number;
158 switch (N) {
159 case 1:
160 case 2:
161 case 4:
162 case 8:
163 case 16:
164 case 32:
165 case 64:
166 case 128:
167 case 256:
168 result = (number - (number & (N-1)));
169 break;
170 default:
171 result = number - (number % N);
172 break;
173 }
174 return result;
175}
176
177static bool m_exynos_gsc_check_src_size(
178 unsigned int *w, unsigned int *h,
179 unsigned int *crop_x, unsigned int *crop_y,
180 unsigned int *crop_w, unsigned int *crop_h,
181 int v4l2_colorformat)
182{
183 if (*w < GSC_MIN_W_SIZE || *h < GSC_MIN_H_SIZE) {
184 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
185 __func__, GSC_MIN_W_SIZE, *w, GSC_MIN_H_SIZE, *h);
186 return false;
187 }
188
189 if (*crop_w < GSC_MIN_W_SIZE || *crop_h < GSC_MIN_H_SIZE) {
190 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
191 __func__, GSC_MIN_W_SIZE,* crop_w, GSC_MIN_H_SIZE, *crop_h);
192 return false;
193 }
194
195 switch (v4l2_colorformat) {
196 // YUV420
197 case V4L2_PIX_FMT_YUV420M:
198 case V4L2_PIX_FMT_YVU420M:
199 case V4L2_PIX_FMT_NV12M:
200 case V4L2_PIX_FMT_NV12MT:
201 case V4L2_PIX_FMT_NV21:
202 case V4L2_PIX_FMT_NV21M:
203 *w = (*w + 15) & ~15;
204 *h = (*h + 15) & ~15;
205 //*w = m_exynos_gsc_multiple_of_n(*w, 16);
206 //*h = m_exynos_gsc_multiple_of_n(*h, 16);
207 *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 4);
208 *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 4);
209 break;
210 // YUV422
211 case V4L2_PIX_FMT_YUYV:
212 case V4L2_PIX_FMT_YUV422P:
213 case V4L2_PIX_FMT_UYVY:
214 case V4L2_PIX_FMT_NV16:
215 case V4L2_PIX_FMT_YVYU:
216 case V4L2_PIX_FMT_VYUY:
217 *h = (*h + 7) & ~7;
218 //*h = m_exynos_gsc_multiple_of_n(*h, 8);
219 *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 4);
220 *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 2);
221 break;
222 // RGB
223 case V4L2_PIX_FMT_RGB32:
224 case V4L2_PIX_FMT_RGB24:
225 case V4L2_PIX_FMT_RGB565:
226 case V4L2_PIX_FMT_BGR32:
227 case V4L2_PIX_FMT_RGB555X:
228 case V4L2_PIX_FMT_RGB444:
229 default:
230 *h = (*h + 7) & ~7;
231 //*h = m_exynos_gsc_multiple_of_n(*h, 8);
232 *crop_w = m_exynos_gsc_multiple_of_n(*crop_w, 2);
233 *crop_h = m_exynos_gsc_multiple_of_n(*crop_h, 2);
234 break;
235 }
236
237 return true;
238}
239
240static bool m_exynos_gsc_check_dst_size(
241 unsigned int *w, unsigned int *h,
242 unsigned int *crop_x, unsigned int *crop_y,
243 unsigned int *crop_w, unsigned int *crop_h,
244 int v4l2_colorformat,
245 int rotation)
246{
247 unsigned int *new_w;
248 unsigned int *new_h;
249 unsigned int *new_crop_w;
250 unsigned int *new_crop_h;
251
252 new_w = w;
253 new_h = h;
254 new_crop_w = crop_w;
255 new_crop_h = crop_h;
256
257 if (*w < GSC_MIN_W_SIZE || *h < GSC_MIN_H_SIZE) {
258 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
259 __func__, GSC_MIN_W_SIZE, *w, GSC_MIN_H_SIZE, *h);
260 return false;
261 }
262
263 if (*crop_w < GSC_MIN_W_SIZE || *crop_h < GSC_MIN_H_SIZE) {
264 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
265 __func__, GSC_MIN_W_SIZE,* crop_w, GSC_MIN_H_SIZE, *crop_h);
266 return false;
267 }
268
269 switch (v4l2_colorformat) {
270 // YUV420
271 case V4L2_PIX_FMT_NV12M:
272 case V4L2_PIX_FMT_NV12MT:
273 case V4L2_PIX_FMT_NV21:
274 case V4L2_PIX_FMT_NV21M:
275 case V4L2_PIX_FMT_YUV420M:
276 case V4L2_PIX_FMT_YVU420M:
277 *new_w = m_exynos_gsc_multiple_of_n(*new_w, 2);
278 *new_h = m_exynos_gsc_multiple_of_n(*new_h, 2);
279 break;
280 // YUV422
281 case V4L2_PIX_FMT_YUYV:
282 case V4L2_PIX_FMT_YUV422P:
283 case V4L2_PIX_FMT_UYVY:
284 case V4L2_PIX_FMT_NV16:
285 case V4L2_PIX_FMT_YVYU:
286 case V4L2_PIX_FMT_VYUY:
287 *new_w = m_exynos_gsc_multiple_of_n(*new_w, 2);
288 break;
289 // RGB
290 case V4L2_PIX_FMT_RGB32:
291 case V4L2_PIX_FMT_RGB24:
292 case V4L2_PIX_FMT_RGB565:
293 case V4L2_PIX_FMT_BGR32:
294 case V4L2_PIX_FMT_RGB555X:
295 case V4L2_PIX_FMT_RGB444:
296 default:
297 break;
298 }
299
300 return true;
301}
302
70007c4e
JC
303static int m_exynos_gsc_output_create(
304 struct GSC_HANDLE *gsc_handle,
305 int dev_num,
306 int out_mode)
307{
e6a0625b 308 struct media_device *media0;
70007c4e
JC
309 struct media_entity *gsc_sd_entity;
310 struct media_entity *gsc_vd_entity;
311 struct media_entity *sink_sd_entity;
312 struct media_link *links;
313 char node[32];
314 char devname[32];
315 unsigned int cap;
316 int i;
317 int fd = 0;
e6a0625b
JC
318
319 Exynos_gsc_In();
320
70007c4e
JC
321 if ((out_mode != GSC_OUT_FIMD) &&
322 (out_mode != GSC_OUT_TV))
323 return -1;
324
325 gsc_handle->out_mode = out_mode;
326 /* GSCX => FIMD_WINX : arbitrary linking is not allowed */
327 if ((out_mode == GSC_OUT_FIMD) &&
52cf3b06 328 (dev_num > 2))
70007c4e
JC
329 return -1;
330
331 /* media0 */
332 sprintf(node, "%s%d", PFX_NODE_MEDIADEV, 0);
333 media0 = exynos_media_open(node);
334 if (media0 == NULL) {
6134b8bb 335 ALOGE("%s::exynos_media_open failed (node=%s)", __func__, node);
70007c4e
JC
336 return false;
337 }
338
339 /* Get the sink subdev entity by name and make the node of sink subdev*/
340 if (out_mode == GSC_OUT_FIMD)
341 sprintf(devname, PFX_FIMD_ENTITY, dev_num);
342 else
343 sprintf(devname, PFX_MXR_ENTITY, 0);
344
e6a0625b 345 sink_sd_entity = exynos_media_get_entity_by_name(media0, devname, strlen(devname));
70007c4e
JC
346 sink_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
347 if ( sink_sd_entity->fd < 0) {
6134b8bb 348 ALOGE("%s:: failed to open sink subdev node", __func__);
70007c4e
JC
349 goto gsc_output_err;
350 }
351
352 /* get GSC video dev & sub dev entity by name*/
353 sprintf(devname, PFX_GSC_VIDEODEV_ENTITY, dev_num);
354 gsc_vd_entity= exynos_media_get_entity_by_name(media0, devname, strlen(devname));
355
356 sprintf(devname, PFX_GSC_SUBDEV_ENTITY, dev_num);
357 gsc_sd_entity= exynos_media_get_entity_by_name(media0, devname, strlen(devname));
358
359 /* gsc sub-dev open */
360 sprintf(devname, PFX_GSC_SUBDEV_ENTITY, dev_num);
361 gsc_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
362
363 /* setup link : GSC : video device --> sub device */
364 for (i = 0; i < (int) gsc_vd_entity->num_links; i++) {
365 links = &gsc_vd_entity->links[i];
366
367 if (links == NULL ||
368 links->source->entity != gsc_vd_entity ||
369 links->sink->entity != gsc_sd_entity) {
370 continue;
371 } else if (exynos_media_setup_link(media0, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
6134b8bb 372 ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
70007c4e
JC
373 __func__, links->source->entity->info.id, links->sink->entity->info.id);
374 return -1;
375 }
376 }
377
378 /* setup link : GSC: sub device --> sink device */
379 for (i = 0; i < (int) gsc_sd_entity->num_links; i++) {
380 links = &gsc_sd_entity->links[i];
381
382 if (links == NULL || links->source->entity != gsc_sd_entity ||
383 links->sink->entity != sink_sd_entity) {
384 continue;
385 } else if (exynos_media_setup_link(media0, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
6134b8bb 386 ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
70007c4e
JC
387 __func__, links->source->entity->info.id, links->sink->entity->info.id);
388 return -1;
389 }
390 }
391
392 /* gsc video-dev open */
393 sprintf(devname, PFX_GSC_VIDEODEV_ENTITY, dev_num);
394 gsc_vd_entity->fd = exynos_v4l2_open_devname(devname, O_RDWR);
395 cap = V4L2_CAP_STREAMING |
396 V4L2_CAP_VIDEO_OUTPUT_MPLANE;
397
398 if (exynos_v4l2_querycap(gsc_vd_entity->fd, cap) == false) {
6134b8bb 399 ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
70007c4e
JC
400 goto gsc_output_err;
401 }
402 gsc_handle->gsc_sd_entity = gsc_sd_entity;
403 gsc_handle->gsc_vd_entity = gsc_vd_entity;
404 gsc_handle->sink_sd_entity = sink_sd_entity;
e6a0625b
JC
405 gsc_handle->media0 = media0;
406
407 Exynos_gsc_Out();
408
70007c4e
JC
409 return 0;
410
411gsc_output_err:
412 /* to do */
413 return -1;
414
415}
416
e6a0625b 417static int m_exynos_gsc_m2m_create(
70007c4e
JC
418 int dev)
419{
420 int fd = 0;
421 int video_node_num;
422 unsigned int cap;
423 char node[32];
424
e6a0625b
JC
425 Exynos_gsc_In();
426
70007c4e
JC
427 switch(dev) {
428 case 0:
429 video_node_num = NODE_NUM_GSC_0;
430 break;
431 case 1:
432 video_node_num = NODE_NUM_GSC_1;
433 break;
434 case 2:
435 video_node_num = NODE_NUM_GSC_2;
436 break;
437 case 3:
438 video_node_num = NODE_NUM_GSC_3;
439 break;
440 default:
6134b8bb 441 ALOGE("%s::unexpected dev(%d) fail", __func__, dev);
70007c4e
JC
442 return -1;
443 break;
444 }
445
446 sprintf(node, "%s%d", PFX_NODE_GSC, video_node_num);
447 fd = exynos_v4l2_open(node, O_RDWR);
448 if (fd < 0) {
6134b8bb 449 ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
70007c4e
JC
450 return -1;
451 }
452
453 cap = V4L2_CAP_STREAMING |
454 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
455 V4L2_CAP_VIDEO_CAPTURE_MPLANE;
456
457 if (exynos_v4l2_querycap(fd, cap) == false) {
6134b8bb 458 ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
70007c4e
JC
459 if (0 < fd)
460 close(fd);
461 fd = 0;
462 return -1;
463 }
e6a0625b
JC
464
465 Exynos_gsc_Out();
466
70007c4e
JC
467 return fd;
468}
469
470
e6a0625b 471static bool m_exynos_gsc_out_destroy(struct GSC_HANDLE *gsc_handle)
70007c4e
JC
472{
473 struct media_link * links;
474 int i;
475
e6a0625b
JC
476 Exynos_gsc_In();
477
70007c4e 478 if (gsc_handle == NULL) {
6134b8bb 479 ALOGE("%s::gsc_handle is NULL", __func__);
70007c4e
JC
480 return false;
481 }
482
483 if (gsc_handle->src.stream_on == true) {
484 if (exynos_gsc_out_stop((void *)gsc_handle) < 0)
6134b8bb 485 ALOGE("%s::exynos_gsc_out_stop() fail", __func__);
70007c4e
JC
486
487 gsc_handle->src.stream_on = false;
488 }
489
e6a0625b 490 /* unlink : gscaler-out --> fimd */
70007c4e
JC
491 for (i = 0; i < (int) gsc_handle->gsc_sd_entity->num_links; i++) {
492 links = &gsc_handle->gsc_sd_entity->links[i];
493
494 if (links == NULL || links->source->entity != gsc_handle->gsc_sd_entity ||
495 links->sink->entity != gsc_handle->sink_sd_entity) {
496 continue;
497 } else if (exynos_media_setup_link(gsc_handle->media0, links->source,
498 links->sink, 0) < 0) {
6134b8bb 499 ALOGE("%s::exynos_media_setup_unlink [src.entity=%d->sink.entity=%d] failed",
70007c4e
JC
500 __func__, links->source->entity->info.id, links->sink->entity->info.id);
501 }
502 }
503
504 close(gsc_handle->gsc_vd_entity->fd);
505 close(gsc_handle->gsc_sd_entity->fd);
506 gsc_handle->gsc_vd_entity->fd = -1;
507 gsc_handle->gsc_vd_entity->fd = -1;
508
e6a0625b
JC
509 Exynos_gsc_Out();
510
70007c4e
JC
511 return true;
512
513}
514
515static bool m_exynos_gsc_destroy(
516 struct GSC_HANDLE *gsc_handle)
517{
e6a0625b
JC
518 Exynos_gsc_In();
519
33aa35f1
DZ
520 /* just in case, we call stop here because we cannot afford to leave
521 * secure side protection on if things failed.
522 */
523 exynos_gsc_m2m_stop(gsc_handle);
70007c4e
JC
524
525 if (0 < gsc_handle->gsc_fd)
526 close(gsc_handle->gsc_fd);
527 gsc_handle->gsc_fd = 0;
528
e6a0625b
JC
529 Exynos_gsc_Out();
530
70007c4e
JC
531 return true;
532}
533
534bool m_exynos_gsc_find_and_trylock_and_create(
535 struct GSC_HANDLE *gsc_handle)
536{
537 int i = 0;
538 bool flag_find_new_gsc = false;
539 unsigned int total_sleep_time = 0;
540
e6a0625b
JC
541 Exynos_gsc_In();
542
70007c4e
JC
543 do {
544 for (i = 0; i < NUM_OF_GSC_HW; i++) {
545 // HACK : HWComposer, HDMI uses gscaler with their own code.
546 // So, This obj_mutex cannot defense their open()
e6a0625b 547 if (i == 0 || i == 3)
70007c4e 548 continue;
70007c4e
JC
549
550 if (exynos_mutex_trylock(gsc_handle->obj_mutex[i]) == true) {
551
552 // destroy old one.
553 m_exynos_gsc_destroy(gsc_handle);
554
555 // create new one.
33aa35f1 556 gsc_handle->gsc_id = i;
e6a0625b 557 gsc_handle->gsc_fd = m_exynos_gsc_m2m_create(i);
70007c4e
JC
558 if (gsc_handle->gsc_fd < 0) {
559 gsc_handle->gsc_fd = 0;
560 exynos_mutex_unlock(gsc_handle->obj_mutex[i]);
561 continue;
562 }
563
564 if (gsc_handle->cur_obj_mutex)
565 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
566
567 gsc_handle->cur_obj_mutex = gsc_handle->obj_mutex[i];
568
569 flag_find_new_gsc = true;
570 break;
571 }
572 }
573
574 // waiting for another process doesn't use gscaler.
575 // we need to make decision how to do.
576 if (flag_find_new_gsc == false) {
577 usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
578 total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
6134b8bb 579 ALOGV("%s::waiting for anthere process doens't use gscaler", __func__);
70007c4e
JC
580 }
581
582 } while( flag_find_new_gsc == false
583 && total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
584
585 if (flag_find_new_gsc == false)
6134b8bb 586 ALOGE("%s::we don't have no available gsc.. fail", __func__);
70007c4e 587
e6a0625b
JC
588 Exynos_gsc_Out();
589
70007c4e
JC
590 return flag_find_new_gsc;
591}
592
593static bool m_exynos_gsc_set_format(
594 int fd,
5f18f784 595 struct gsc_info *info)
70007c4e 596{
e6a0625b
JC
597 Exynos_gsc_In();
598
70007c4e
JC
599 struct v4l2_requestbuffers req_buf;
600 int plane_count;
601
602 plane_count = m_gsc_get_plane_count(info->v4l2_colorformat);
603 if (plane_count < 0) {
6134b8bb 604 ALOGE("%s::not supported v4l2_colorformat", __func__);
70007c4e
JC
605 return false;
606 }
607
70007c4e 608 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
6134b8bb 609 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
70007c4e
JC
610 return false;
611 }
612
613 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_VFLIP, info->flip_horizontal) < 0) {
6134b8bb 614 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__);
70007c4e
JC
615 return false;
616 }
617
618 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_HFLIP, info->flip_vertical) < 0) {
6134b8bb 619 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
70007c4e
JC
620 return false;
621 }
bcd3f11d
GH
622
623 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CSC_RANGE, info->csc_range) < 0) {
624 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
625 return false;
626 }
e6a0625b 627 info->format.type = info->buf_type;
70007c4e
JC
628 info->format.fmt.pix_mp.width = info->width;
629 info->format.fmt.pix_mp.height = info->height;
630 info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
631 info->format.fmt.pix_mp.field = V4L2_FIELD_ANY;
632 info->format.fmt.pix_mp.num_planes = plane_count;
633
634 if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
6134b8bb 635 ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
70007c4e
JC
636 return false;
637 }
638
639 info->crop.type = info->buf_type;
640 info->crop.c.left = info->crop_left;
641 info->crop.c.top = info->crop_top;
642 info->crop.c.width = info->crop_width;
643 info->crop.c.height = info->crop_height;
644
645 if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
6134b8bb 646 ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
70007c4e
JC
647 return false;
648 }
649
650 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
6134b8bb 651 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
70007c4e
JC
652 return false;
653 }
654
655 req_buf.count = 1;
656 req_buf.type = info->buf_type;
776bd695 657 req_buf.memory = V4L2_MEMORY_DMABUF;
70007c4e 658 if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
6134b8bb 659 ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
70007c4e
JC
660 return false;
661 }
662
e6a0625b
JC
663 Exynos_gsc_Out();
664
70007c4e
JC
665 return true;
666}
667
668static bool m_exynos_gsc_set_addr(
669 int fd,
670 struct gsc_info *info)
671{
672 unsigned int i;
673 unsigned int plane_size[NUM_OF_GSC_PLANES];
674
675 m_gsc_get_plane_size(plane_size,
676 info->width,
677 info->height,
678 info->v4l2_colorformat);
679
680 info->buffer.index = 0;
9f6d8287 681 info->buffer.flags = V4L2_BUF_FLAG_USE_SYNC;
70007c4e 682 info->buffer.type = info->buf_type;
776bd695 683 info->buffer.memory = V4L2_MEMORY_DMABUF;
70007c4e
JC
684 info->buffer.m.planes = info->planes;
685 info->buffer.length = info->format.fmt.pix_mp.num_planes;
9f6d8287 686 info->buffer.reserved = info->acquireFenceFd;
70007c4e
JC
687
688 for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
776bd695 689 info->buffer.m.planes[i].m.fd = (int)info->addr[i];
70007c4e
JC
690 info->buffer.m.planes[i].length = plane_size[i];
691 info->buffer.m.planes[i].bytesused = 0;
692 }
693
694 if (exynos_v4l2_qbuf(fd, &info->buffer) < 0) {
6134b8bb 695 ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
70007c4e
JC
696 return false;
697 }
9f6d8287
BG
698 info->buffer_queued = true;
699
700 info->releaseFenceFd = info->buffer.reserved;
70007c4e
JC
701
702 return true;
703}
704
705void *exynos_gsc_create(
706 void)
707{
708 int i = 0;
709 int op_id = 0;
710 char mutex_name[32];
711
e6a0625b
JC
712 Exynos_gsc_In();
713
70007c4e
JC
714 struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
715 if (gsc_handle == NULL) {
6134b8bb 716 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
70007c4e
JC
717 goto err;
718 }
719
720 gsc_handle->gsc_fd = 0;
721 memset(&gsc_handle->src, 0, sizeof(struct gsc_info));
722 memset(&gsc_handle->dst, 0, sizeof(struct gsc_info));
723
724 gsc_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
725 gsc_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
726
727 gsc_handle->op_mutex = NULL;
728 for (i = 0; i < NUM_OF_GSC_HW; i++)
729 gsc_handle->obj_mutex[i] = NULL;
730
731 gsc_handle->cur_obj_mutex = NULL;
732 gsc_handle->flag_local_path = false;
733 gsc_handle->flag_exclusive_open = false;
734
735 srand(time(NULL));
736 op_id = rand() % 1000000; // just make random id
737 sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
738 gsc_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
739 if (gsc_handle->op_mutex == NULL) {
6134b8bb 740 ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
70007c4e
JC
741 goto err;
742 }
743
744 exynos_mutex_lock(gsc_handle->op_mutex);
745
746 // check if it is available
747 for (i = 0; i < NUM_OF_GSC_HW; i++) {
748 sprintf(mutex_name, "%sObject%d", LOG_TAG, i);
749
750 gsc_handle->obj_mutex[i] = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
751 if (gsc_handle->obj_mutex[i] == NULL) {
6134b8bb 752 ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
70007c4e
JC
753 goto err;
754 }
755 }
756
757 if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle) == false) {
6134b8bb 758 ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__);
70007c4e
JC
759 goto err;
760 }
761
762 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
763 exynos_mutex_unlock(gsc_handle->op_mutex);
764
765 return (void *)gsc_handle;
766
767err:
768 if (gsc_handle) {
769 m_exynos_gsc_destroy(gsc_handle);
770
771 if (gsc_handle->cur_obj_mutex)
772 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
773
774 for (i = 0; i < NUM_OF_GSC_HW; i++) {
775 if ((gsc_handle->obj_mutex[i] != NULL) &&
e6a0625b 776 (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
70007c4e 777 if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
6134b8bb 778 ALOGE("%s::exynos_mutex_destroy() fail", __func__);
70007c4e
JC
779 }
780 }
781
782 if (gsc_handle->op_mutex)
783 exynos_mutex_unlock(gsc_handle->op_mutex);
784
785 if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
6134b8bb 786 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
70007c4e
JC
787
788 free(gsc_handle);
789 }
790
e6a0625b
JC
791 Exynos_gsc_Out();
792
70007c4e
JC
793 return NULL;
794}
795
796void *exynos_gsc_reserve(int dev_num)
797{
798 char mutex_name[32];
799 unsigned int total_sleep_time = 0;
800 bool gsc_flag = false;
801
802 if ((dev_num < 0) || (dev_num >= NUM_OF_GSC_HW)) {
6134b8bb 803 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
70007c4e
JC
804 return NULL;
805 }
806
807 struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
808 if (gsc_handle == NULL) {
6134b8bb 809 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
70007c4e
JC
810 goto err;
811 }
812
813 gsc_handle->gsc_fd = -1;
814 gsc_handle->op_mutex = NULL;
815 gsc_handle->cur_obj_mutex = NULL;
816
817 sprintf(mutex_name, "%sObject%d", LOG_TAG, dev_num);
818 gsc_handle->cur_obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
819 if (gsc_handle->cur_obj_mutex == NULL) {
6134b8bb 820 ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
70007c4e
JC
821 goto err;
822 }
823
824 do {
825 if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == true) {
826 gsc_flag = true;
827 break;
828 }
829 usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
830 total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
6134b8bb 831 ALOGV("%s::waiting for another process to release the requested gscaler", __func__);
70007c4e
JC
832 } while(total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
833
834 if (gsc_flag == true)
835 return (void *)gsc_handle;
836
837err:
838 if (gsc_handle) {
839 free(gsc_handle);
840 }
841
842 return NULL;
843}
844
845void exynos_gsc_release(void *handle)
846{
847 struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)handle;
848
849 if (handle == NULL) {
6134b8bb 850 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
851 return;
852 }
853
854 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
855 exynos_mutex_destroy(gsc_handle->cur_obj_mutex);
856 free(gsc_handle);
857 return;
858}
859
860void *exynos_gsc_create_exclusive(
861 int dev_num,
862 int mode,
33aa35f1
DZ
863 int out_mode,
864 int allow_drm)
70007c4e
JC
865{
866 int i = 0;
867 int op_id = 0;
868 char mutex_name[32];
869 unsigned int total_sleep_time = 0;
870 bool gsc_flag = false;
871 int ret = 0;
e6a0625b
JC
872
873 Exynos_gsc_In();
874
70007c4e 875 if ((dev_num < 0) || (dev_num >= NUM_OF_GSC_HW)) {
6134b8bb 876 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
70007c4e
JC
877 return NULL;
878 }
879
880 if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
6134b8bb 881 ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
70007c4e
JC
882 return NULL;
883 }
884
33aa35f1
DZ
885 /* currently only gscalers 0 and 3 are DRM capable */
886 if (allow_drm && (dev_num != 0 && dev_num != 3)) {
887 ALOGE("%s::fail:: gscaler %d does not support drm\n", __func__,
888 dev_num);
889 return NULL;
890 }
891
70007c4e
JC
892 struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)malloc(sizeof(struct GSC_HANDLE));
893 if (gsc_handle == NULL) {
6134b8bb 894 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__);
70007c4e
JC
895 goto err;
896 }
70007c4e 897 memset(gsc_handle, 0, sizeof(struct GSC_HANDLE));
e6a0625b 898 gsc_handle->gsc_fd = -1;
70007c4e 899 gsc_handle->gsc_mode = mode;
33aa35f1
DZ
900 gsc_handle->gsc_id = dev_num;
901 gsc_handle->allow_drm = allow_drm;
70007c4e
JC
902
903 gsc_handle->src.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
904 gsc_handle->dst.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
905
906 gsc_handle->op_mutex = NULL;
907 for (i = 0; i < NUM_OF_GSC_HW; i++)
908 gsc_handle->obj_mutex[i] = NULL;
909
910 gsc_handle->cur_obj_mutex = NULL;
911 gsc_handle->flag_local_path = false;
912 gsc_handle->flag_exclusive_open = true;
913
914 srand(time(NULL));
915 op_id = rand() % 1000000; // just make random id
916 sprintf(mutex_name, "%sOp%d", LOG_TAG, op_id);
917 gsc_handle->op_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE, mutex_name);
918 if (gsc_handle->op_mutex == NULL) {
6134b8bb 919 ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
70007c4e
JC
920 goto err;
921 }
922
923 exynos_mutex_lock(gsc_handle->op_mutex);
924
925 sprintf(mutex_name, "%sObject%d", LOG_TAG, dev_num);
926 gsc_handle->cur_obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
927 if (gsc_handle->cur_obj_mutex == NULL) {
6134b8bb 928 ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
70007c4e
JC
929 goto err;
930 }
931
932 do {
933 if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == true) {
934 if (mode == GSC_M2M_MODE) {
e6a0625b
JC
935 gsc_handle->gsc_fd = m_exynos_gsc_m2m_create(dev_num);
936 if (gsc_handle->gsc_fd < 0) {
937 ALOGE("%s::m_exynos_gsc_m2m_create(%i) fail", __func__, dev_num);
938 goto err;
939 }
70007c4e
JC
940 } else if (mode == GSC_OUTPUT_MODE) {
941 ret = m_exynos_gsc_output_create(gsc_handle, dev_num, out_mode);
942 if (ret < 0) {
6134b8bb 943 ALOGE("%s::m_exynos_gsc_output_create(%i) fail", __func__, dev_num);
70007c4e
JC
944 goto err;
945 }
946 }
947 /*else
948 gsc_handle->gsc_fd = m_exynos_gsc_capture_create(dev_num);*/
e6a0625b 949
70007c4e
JC
950 gsc_flag = true;
951 break;
952 }
953 usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
954 total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
6134b8bb 955 ALOGV("%s::waiting for anthere process doens't use gscaler", __func__);
70007c4e
JC
956 } while(total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
957
958 exynos_mutex_unlock(gsc_handle->op_mutex);
e6a0625b
JC
959 if (gsc_flag == true) {
960 Exynos_gsc_Out();
961 return (void *)gsc_handle;
962 }
70007c4e
JC
963
964err:
965 if (gsc_handle) {
966 m_exynos_gsc_destroy(gsc_handle);
967
968 if (gsc_handle->cur_obj_mutex)
969 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
970
971 for (i = 0; i < NUM_OF_GSC_HW; i++) {
972 if ((gsc_handle->obj_mutex[i] != NULL) &&
e6a0625b 973 (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
70007c4e 974 if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
6134b8bb 975 ALOGE("%s::exynos_mutex_destroy() fail", __func__);
70007c4e
JC
976 }
977 }
978
979 if (gsc_handle->op_mutex)
980 exynos_mutex_unlock(gsc_handle->op_mutex);
981
982 if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
6134b8bb 983 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
70007c4e
JC
984
985 free(gsc_handle);
986 }
987
e6a0625b
JC
988 Exynos_gsc_Out();
989
70007c4e
JC
990 return NULL;
991}
992
993void exynos_gsc_destroy(
994 void *handle)
995{
996 int i = 0;
997 struct GSC_HANDLE *gsc_handle = (struct GSC_HANDLE *)handle;
998
e6a0625b
JC
999 Exynos_gsc_In();
1000
70007c4e 1001 if (handle == NULL) {
6134b8bb 1002 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1003 return;
1004 }
1005
1006 exynos_mutex_lock(gsc_handle->op_mutex);
1007
1008 if (gsc_handle->flag_exclusive_open == false)
1009 exynos_mutex_lock(gsc_handle->cur_obj_mutex);
1010
1011 if (gsc_handle->gsc_mode == GSC_OUTPUT_MODE)
e6a0625b
JC
1012 m_exynos_gsc_out_destroy(gsc_handle);
1013 else
1014 m_exynos_gsc_destroy(gsc_handle);
70007c4e
JC
1015
1016 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
1017
1018 for (i = 0; i < NUM_OF_GSC_HW; i++) {
1019 if ((gsc_handle->obj_mutex[i] != NULL) &&
e6a0625b 1020 (exynos_mutex_get_created_status(gsc_handle->obj_mutex[i]) == true)) {
70007c4e 1021 if (exynos_mutex_destroy(gsc_handle->obj_mutex[i]) == false)
6134b8bb 1022 ALOGE("%s::exynos_mutex_destroy(obj_mutex) fail", __func__);
70007c4e
JC
1023 }
1024 }
1025
1026 exynos_mutex_unlock(gsc_handle->op_mutex);
1027
1028 if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)
6134b8bb 1029 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__);
70007c4e
JC
1030
1031 if (gsc_handle)
1032 free(gsc_handle);
e6a0625b
JC
1033
1034 Exynos_gsc_Out();
1035
70007c4e
JC
1036}
1037
1038int exynos_gsc_set_src_format(
1039 void *handle,
1040 unsigned int width,
1041 unsigned int height,
1042 unsigned int crop_left,
1043 unsigned int crop_top,
1044 unsigned int crop_width,
1045 unsigned int crop_height,
1046 unsigned int v4l2_colorformat,
e6a0625b
JC
1047 unsigned int cacheable,
1048 unsigned int mode_drm)
70007c4e 1049{
e6a0625b
JC
1050 Exynos_gsc_In();
1051
70007c4e
JC
1052 struct GSC_HANDLE *gsc_handle;
1053 gsc_handle = (struct GSC_HANDLE *)handle;
1054
1055 if (handle == NULL) {
6134b8bb 1056 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1057 return -1;
1058 }
1059
1060 exynos_mutex_lock(gsc_handle->op_mutex);
1061
1062 gsc_handle->src.width = width;
1063 gsc_handle->src.height = height;
1064 gsc_handle->src.crop_left = crop_left;
1065 gsc_handle->src.crop_top = crop_top;
1066 gsc_handle->src.crop_width = crop_width;
1067 gsc_handle->src.crop_height = crop_height;
1068 gsc_handle->src.v4l2_colorformat = v4l2_colorformat;
1069 gsc_handle->src.cacheable = cacheable;
e6a0625b 1070 gsc_handle->src.mode_drm = mode_drm;
e2426aa8 1071 gsc_handle->src.dirty = true;
70007c4e 1072
70007c4e
JC
1073
1074 exynos_mutex_unlock(gsc_handle->op_mutex);
1075
e6a0625b
JC
1076 Exynos_gsc_Out();
1077
70007c4e
JC
1078 return 0;
1079}
1080
1081int exynos_gsc_set_dst_format(
1082 void *handle,
1083 unsigned int width,
1084 unsigned int height,
1085 unsigned int crop_left,
1086 unsigned int crop_top,
1087 unsigned int crop_width,
1088 unsigned int crop_height,
1089 unsigned int v4l2_colorformat,
e6a0625b 1090 unsigned int cacheable,
bcd3f11d
GH
1091 unsigned int mode_drm,
1092 unsigned int narrowRgb)
70007c4e 1093{
e6a0625b
JC
1094 Exynos_gsc_In();
1095
70007c4e
JC
1096 struct GSC_HANDLE *gsc_handle;
1097 gsc_handle = (struct GSC_HANDLE *)handle;
1098
1099 if (handle == NULL) {
6134b8bb 1100 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1101 return -1;
1102 }
1103
1104 exynos_mutex_lock(gsc_handle->op_mutex);
1105
1106 gsc_handle->dst.width = width;
1107 gsc_handle->dst.height = height;
1108 gsc_handle->dst.crop_left = crop_left;
1109 gsc_handle->dst.crop_top = crop_top;
1110 gsc_handle->dst.crop_width = crop_width;
1111 gsc_handle->dst.crop_height = crop_height;
1112 gsc_handle->dst.v4l2_colorformat = v4l2_colorformat;
1113 gsc_handle->dst.cacheable = cacheable;
e6a0625b 1114 gsc_handle->dst.mode_drm = mode_drm;
e2426aa8 1115 gsc_handle->dst.dirty = true;
bcd3f11d 1116 gsc_handle->dst.csc_range = !narrowRgb;
70007c4e 1117
70007c4e
JC
1118 exynos_mutex_unlock(gsc_handle->op_mutex);
1119
e6a0625b
JC
1120 Exynos_gsc_Out();
1121 return 0;
1122}
1123
70007c4e
JC
1124int exynos_gsc_set_rotation(
1125 void *handle,
1126 int rotation,
1127 int flip_horizontal,
1128 int flip_vertical)
1129{
1130 int ret = -1;
1131 struct GSC_HANDLE *gsc_handle;
1132 gsc_handle = (struct GSC_HANDLE *)handle;
1133
1134 if (handle == NULL) {
6134b8bb 1135 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1136 return ret;
1137 }
1138
1139 exynos_mutex_lock(gsc_handle->op_mutex);
1140
1141 int new_rotation = rotation % 360;
1142
1143 if (new_rotation % 90 != 0) {
6134b8bb 1144 ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__, rotation);
70007c4e
JC
1145 goto done;
1146 }
1147
1148 if(new_rotation < 0)
1149 new_rotation = -new_rotation;
1150
1151 gsc_handle->dst.rotation = new_rotation;
1152 gsc_handle->dst.flip_horizontal = flip_horizontal;
1153 gsc_handle->dst.flip_vertical = flip_vertical;
1154
1155 ret = 0;
1156done:
1157 exynos_mutex_unlock(gsc_handle->op_mutex);
1158
1159 return ret;
1160}
1161
1162int exynos_gsc_set_src_addr(
1163 void *handle,
9f6d8287
BG
1164 void *addr[3],
1165 int acquireFenceFd)
70007c4e
JC
1166{
1167 struct GSC_HANDLE *gsc_handle;
1168 gsc_handle = (struct GSC_HANDLE *)handle;
1169
e6a0625b
JC
1170 Exynos_gsc_In();
1171
70007c4e 1172 if (handle == NULL) {
6134b8bb 1173 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1174 return -1;
1175 }
1176
1177 exynos_mutex_lock(gsc_handle->op_mutex);
1178
1179 gsc_handle->src.addr[0] = addr[0];
1180 gsc_handle->src.addr[1] = addr[1];
1181 gsc_handle->src.addr[2] = addr[2];
9f6d8287 1182 gsc_handle->src.acquireFenceFd = acquireFenceFd;
70007c4e
JC
1183
1184 exynos_mutex_unlock(gsc_handle->op_mutex);
1185
e6a0625b
JC
1186 Exynos_gsc_Out();
1187
70007c4e
JC
1188 return 0;
1189}
1190
1191int exynos_gsc_set_dst_addr(
1192 void *handle,
9f6d8287
BG
1193 void *addr[3],
1194 int acquireFenceFd)
70007c4e
JC
1195{
1196 struct GSC_HANDLE *gsc_handle;
1197 gsc_handle = (struct GSC_HANDLE *)handle;
994ebe9b 1198 int ret = 0;
70007c4e 1199
e6a0625b
JC
1200 Exynos_gsc_In();
1201
70007c4e 1202 if (handle == NULL) {
6134b8bb 1203 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1204 return -1;
1205 }
1206
1207 exynos_mutex_lock(gsc_handle->op_mutex);
1208
1209 gsc_handle->dst.addr[0] = addr[0];
1210 gsc_handle->dst.addr[1] = addr[1];
1211 gsc_handle->dst.addr[2] = addr[2];
9f6d8287 1212 gsc_handle->dst.acquireFenceFd = acquireFenceFd;
70007c4e 1213
70007c4e
JC
1214
1215 exynos_mutex_unlock(gsc_handle->op_mutex);
1216
e6a0625b
JC
1217 Exynos_gsc_Out();
1218
994ebe9b 1219 return ret;
70007c4e
JC
1220}
1221
1222static void rotateValueHAL2GSC(unsigned int transform,
1223 unsigned int *rotate,
1224 unsigned int *hflip,
1225 unsigned int *vflip)
1226{
1227 int rotate_flag = transform & 0x7;
1228 *rotate = 0;
1229 *hflip = 0;
1230 *vflip = 0;
1231
1232 switch (rotate_flag) {
1233 case HAL_TRANSFORM_ROT_90:
1234 *rotate = 90;
1235 break;
1236 case HAL_TRANSFORM_ROT_180:
1237 *rotate = 180;
1238 break;
1239 case HAL_TRANSFORM_ROT_270:
1240 *rotate = 270;
1241 break;
1242 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
1243 *rotate = 90;
1244 *vflip = 1; /* set vflip to compensate the rot & flip order. */
1245 break;
1246 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
1247 *rotate = 90;
1248 *hflip = 1; /* set hflip to compensate the rot & flip order. */
1249 break;
1250 case HAL_TRANSFORM_FLIP_H:
1251 *hflip = 1;
1252 break;
1253 case HAL_TRANSFORM_FLIP_V:
1254 *vflip = 1;
1255 break;
1256 default:
1257 break;
1258 }
70007c4e
JC
1259}
1260
1261static bool get_plane_size(int V4L2_PIX,
1262 unsigned int * size,
1263 unsigned int frame_size,
e6a0625b 1264 int src_planes)
70007c4e 1265{
e6a0625b 1266 unsigned int frame_ratio = 1;
70007c4e
JC
1267 int src_bpp = get_yuv_bpp(V4L2_PIX);
1268
1269 src_planes = (src_planes == -1) ? 1 : src_planes;
1270 frame_ratio = 8 * (src_planes -1) / (src_bpp - 8);
1271
1272 switch (src_planes) {
1273 case 1:
1274 switch (V4L2_PIX) {
1275 case V4L2_PIX_FMT_BGR32:
1276 case V4L2_PIX_FMT_RGB32:
1277 size[0] = frame_size << 2;
1278 break;
1279 case V4L2_PIX_FMT_RGB565X:
1280 case V4L2_PIX_FMT_NV16:
1281 case V4L2_PIX_FMT_NV61:
1282 case V4L2_PIX_FMT_YUYV:
1283 case V4L2_PIX_FMT_UYVY:
1284 case V4L2_PIX_FMT_VYUY:
1285 case V4L2_PIX_FMT_YVYU:
1286 size[0] = frame_size << 1;
1287 break;
1288 case V4L2_PIX_FMT_YUV420:
1289 case V4L2_PIX_FMT_NV12:
1290 case V4L2_PIX_FMT_NV21:
66e91991 1291 case V4L2_PIX_FMT_NV21M:
70007c4e
JC
1292 size[0] = (frame_size * 3) >> 1;
1293 break;
1294 default:
6134b8bb 1295 ALOGE("%s::invalid color type", __func__);
70007c4e
JC
1296 return false;
1297 break;
1298 }
1299 size[1] = 0;
1300 size[2] = 0;
1301 break;
1302 case 2:
1303 size[0] = frame_size;
1304 size[1] = frame_size / frame_ratio;
1305 size[2] = 0;
1306 break;
1307 case 3:
1308 size[0] = frame_size;
1309 size[1] = frame_size / frame_ratio;
1310 size[2] = frame_size / frame_ratio;
1311 break;
1312 default:
6134b8bb 1313 ALOGE("%s::invalid color foarmt", __func__);
70007c4e
JC
1314 return false;
1315 break;
1316 }
1317
1318 return true;
1319}
1320
e6a0625b
JC
1321int exynos_gsc_m2m_config(void *handle,
1322 exynos_gsc_img *src_img,
1323 exynos_gsc_img *dst_img)
1324{
1325 struct GSC_HANDLE *gsc_handle;
1326 int32_t src_color_space;
1327 int32_t dst_color_space;
1328 int ret;
1329 unsigned int rotate;
1330 unsigned int hflip;
1331 unsigned int vflip;
1332
1333 Exynos_gsc_In();
1334
1335 gsc_handle = (struct GSC_HANDLE *)handle;
33aa35f1 1336 if (gsc_handle == NULL) {
e6a0625b
JC
1337 ALOGE("%s::gsc_handle == NULL() fail", __func__);
1338 return -1;
1339 }
1340
33aa35f1
DZ
1341 if ((src_img->drmMode && !gsc_handle->allow_drm) ||
1342 (src_img->drmMode != dst_img->drmMode)) {
1343 ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
1344 __func__, gsc_handle->gsc_id,
1345 src_img->drmMode, dst_img->drmMode);
1346 return -1;
1347 }
1348
e6a0625b
JC
1349 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1350 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1351 rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1352 exynos_gsc_set_rotation(gsc_handle, rotate, hflip, vflip);
1353
1354 ret = exynos_gsc_set_src_format(gsc_handle, src_img->fw, src_img->fh,
1355 src_img->x, src_img->y, src_img->w, src_img->h,
1356 src_color_space, src_img->cacheable, src_img->drmMode);
1357 if (ret < 0) {
1358 ALOGE("%s: fail: exynos_gsc_set_src_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1359 __func__, src_img->fw, src_img->fh, src_img->x, src_img->y, src_img->w, src_img->h,
1360 src_color_space, src_img->rot);
1361 return -1;
1362 }
1363
1364 ret = exynos_gsc_set_dst_format(gsc_handle, dst_img->fw, dst_img->fh,
1365 dst_img->x, dst_img->y, dst_img->w, dst_img->h,
bcd3f11d
GH
1366 dst_color_space, dst_img->cacheable, dst_img->drmMode,
1367 dst_img->narrowRgb);
e6a0625b
JC
1368 if (ret < 0) {
1369 ALOGE("%s: fail: exynos_gsc_set_dst_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1370 __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y, dst_img->w, dst_img->h,
1371 src_color_space, dst_img->rot);
1372 return -1;
1373 }
1374
1375 Exynos_gsc_Out();
1376
1377 return 0;
1378}
1379
70007c4e 1380int exynos_gsc_out_config(void *handle,
e6a0625b
JC
1381 exynos_gsc_img *src_img,
1382 exynos_gsc_img *dst_img)
70007c4e
JC
1383{
1384 struct GSC_HANDLE *gsc_handle;
1385 struct v4l2_format fmt;
1386 struct v4l2_crop crop;
1387 struct v4l2_requestbuffers reqbuf;
1388 struct v4l2_subdev_format sd_fmt;
1389 struct v4l2_subdev_crop sd_crop;
1390 int i;
1391 unsigned int rotate;
1392 unsigned int hflip;
1393 unsigned int vflip;
1394 unsigned int plane_size[NUM_OF_GSC_PLANES];
cd63257f 1395 bool rgb;
bcd3f11d 1396 int csc_range = !dst_img->narrowRgb;
70007c4e
JC
1397
1398 struct v4l2_rect dst_rect;
1399 int32_t src_color_space;
1400 int32_t dst_color_space;
1401 int32_t src_planes;
e6a0625b 1402
70007c4e
JC
1403 gsc_handle = (struct GSC_HANDLE *)handle;
1404 if (gsc_handle == NULL) {
6134b8bb 1405 ALOGE("%s::gsc_handle == NULL() fail", __func__);
70007c4e
JC
1406 return -1;
1407 }
1408
e6a0625b
JC
1409 Exynos_gsc_In();
1410
70007c4e 1411 if (gsc_handle->src.stream_on != false) {
6134b8bb 1412 ALOGE("Error: Src is already streamed on !!!!");
70007c4e
JC
1413 return -1;
1414 }
1415
e6a0625b
JC
1416 memcpy(&gsc_handle->src_img, src_img, sizeof(exynos_gsc_img));
1417 memcpy(&gsc_handle->dst_img, dst_img, sizeof(exynos_gsc_img));
70007c4e
JC
1418 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1419 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1420 src_planes = get_yuv_planes(src_color_space);
ba718a43
BG
1421 src_planes = (src_planes == -1) ? 1 : src_planes;
1422 rgb = get_yuv_planes(dst_color_space) == -1;
70007c4e
JC
1423 rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1424
e76fa944
RSZ
1425 if (m_exynos_gsc_check_src_size(&gsc_handle->src_img.fw, &gsc_handle->src_img.fh,
1426 &gsc_handle->src_img.x, &gsc_handle->src_img.y,
1427 &gsc_handle->src_img.w, &gsc_handle->src_img.h,
1428 src_color_space) == false) {
1429 ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__);
1430 return -1;
1431 }
1432
1433 if (m_exynos_gsc_check_dst_size(&gsc_handle->dst_img.fw, &gsc_handle->dst_img.fh,
1434 &gsc_handle->dst_img.x, &gsc_handle->dst_img.y,
1435 &gsc_handle->dst_img.w, &gsc_handle->dst_img.h,
1436 dst_color_space,
1437 rotate) == false) {
1438 ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__);
1439 return -1;
70007c4e
JC
1440 }
1441
1442 /*set: src v4l2_buffer*/
1443 gsc_handle->src.src_buf_idx = 0;
1444 gsc_handle->src.qbuf_cnt = 0;
70007c4e
JC
1445 /* set format: src pad of GSC sub-dev*/
1446 sd_fmt.pad = GSCALER_SUBDEV_PAD_SOURCE;
1447 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
aad0a4c5
BG
1448 if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1449 sd_fmt.format.width = gsc_handle->dst_img.fw;
1450 sd_fmt.format.height = gsc_handle->dst_img.fh;
1451 } else {
1452 sd_fmt.format.width = gsc_handle->dst_img.w;
1453 sd_fmt.format.height = gsc_handle->dst_img.h;
1454 }
cd63257f
GH
1455 sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1456 V4L2_MBUS_FMT_YUV8_1X24;
70007c4e 1457 if (exynos_subdev_s_fmt(gsc_handle->gsc_sd_entity->fd, &sd_fmt) < 0) {
6134b8bb 1458 ALOGE("%s::GSC subdev set format failed", __func__);
70007c4e
JC
1459 return -1;
1460 }
1461
1462 /* set crop: src crop of GSC sub-dev*/
1463 sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
1464 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
aad0a4c5
BG
1465 if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1466 sd_crop.rect.left = gsc_handle->dst_img.x;
1467 sd_crop.rect.top = gsc_handle->dst_img.y;
1468 sd_crop.rect.width = gsc_handle->dst_img.w;
1469 sd_crop.rect.height = gsc_handle->dst_img.h;
1470 } else {
1471 sd_crop.rect.left = 0;
1472 sd_crop.rect.top = 0;
1473 sd_crop.rect.width = gsc_handle->dst_img.w;
1474 sd_crop.rect.height = gsc_handle->dst_img.h;
1475 }
70007c4e 1476 if (exynos_subdev_s_crop(gsc_handle->gsc_sd_entity->fd, &sd_crop) < 0) {
6134b8bb 1477 ALOGE("%s::GSC subdev set crop failed", __func__);
70007c4e
JC
1478 return -1;
1479 }
1480
1481 /* sink pad is connected to GSC out */
1482 /* set format: sink sub-dev */
aad0a4c5 1483 if (gsc_handle->out_mode == GSC_OUT_FIMD) {
70007c4e 1484 sd_fmt.pad = FIMD_SUBDEV_PAD_SINK;
aad0a4c5
BG
1485 sd_fmt.format.width = gsc_handle->dst_img.w;
1486 sd_fmt.format.height = gsc_handle->dst_img.h;
1487 } else {
70007c4e 1488 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SINK;
aad0a4c5
BG
1489 sd_fmt.format.width = gsc_handle->dst_img.w + gsc_handle->dst_img.x*2;
1490 sd_fmt.format.height = gsc_handle->dst_img.h + gsc_handle->dst_img.y*2;
1491 }
e6a0625b 1492
70007c4e 1493 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
cd63257f
GH
1494 sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1495 V4L2_MBUS_FMT_YUV8_1X24;
70007c4e 1496 if (exynos_subdev_s_fmt(gsc_handle->sink_sd_entity->fd, &sd_fmt) < 0) {
6134b8bb 1497 ALOGE("%s::sink:set format failed (PAD=%d)", __func__, sd_fmt.pad);
70007c4e
JC
1498 return -1;
1499 }
1500
1501 /* set crop: sink sub-dev */
1502 if (gsc_handle->out_mode == GSC_OUT_FIMD)
1503 sd_crop.pad = FIMD_SUBDEV_PAD_SINK;
1504 else
1505 sd_crop.pad = MIXER_V_SUBDEV_PAD_SINK;
1506
1507 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
aad0a4c5
BG
1508 if (gsc_handle->out_mode == GSC_OUT_FIMD) {
1509 sd_crop.rect.left = gsc_handle->dst_img.x;
1510 sd_crop.rect.top = gsc_handle->dst_img.y;
1511 sd_crop.rect.width = gsc_handle->dst_img.w;
1512 sd_crop.rect.height = gsc_handle->dst_img.h;
1513 } else {
1514 sd_crop.rect.left = 0;
1515 sd_crop.rect.top = 0;
1516 sd_crop.rect.width = gsc_handle->dst_img.w;
1517 sd_crop.rect.height = gsc_handle->dst_img.h;
1518 }
70007c4e 1519 if (exynos_subdev_s_crop(gsc_handle->sink_sd_entity->fd, &sd_crop) < 0) {
6134b8bb 1520 ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__, sd_crop.pad);
70007c4e
JC
1521 return -1;
1522 }
1523
aad0a4c5
BG
1524 if (gsc_handle->out_mode != GSC_OUT_FIMD) {
1525 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
1526 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1527 sd_fmt.format.width = gsc_handle->dst_img.w + gsc_handle->dst_img.x*2;
1528 sd_fmt.format.height = gsc_handle->dst_img.h + gsc_handle->dst_img.y*2;
1529 sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
1530 if (exynos_subdev_s_fmt(gsc_handle->sink_sd_entity->fd, &sd_fmt) < 0) {
1531 ALOGE("%s::sink:set format failed (PAD=%d)", __func__, sd_fmt.pad);
1532 return -1;
1533 }
1534
1535 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
1536 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1537 sd_crop.rect.left = gsc_handle->dst_img.x;
1538 sd_crop.rect.top = gsc_handle->dst_img.y;
1539 sd_crop.rect.width = gsc_handle->dst_img.w;
1540 sd_crop.rect.height = gsc_handle->dst_img.h;
1541 if (exynos_subdev_s_crop(gsc_handle->sink_sd_entity->fd, &sd_crop) < 0) {
1542 ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__, sd_crop.pad);
1543 return -1;
1544 }
1545 }
1546
70007c4e 1547 /*set GSC ctrls */
e6a0625b 1548 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_ROTATE, rotate) < 0) {
6134b8bb 1549 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed", __func__, rotate);
70007c4e
JC
1550 return -1;
1551 }
1552
e6a0625b 1553 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_HFLIP, hflip) < 0) {
6134b8bb 1554 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed", __func__, hflip);
70007c4e
JC
1555 return -1;
1556 }
1557
e6a0625b 1558 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_VFLIP, vflip) < 0) {
6134b8bb 1559 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed", __func__, vflip);
70007c4e
JC
1560 return -1;
1561 }
1562
e6a0625b 1563 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_CACHEABLE, 1) < 0) {
6134b8bb 1564 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed", __func__);
70007c4e
JC
1565 return -1;
1566 }
1567
0db2e831
SK
1568 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd,
1569 V4L2_CID_CONTENT_PROTECTION, gsc_handle->src_img.drmMode) < 0) {
1570 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail", __func__);
1571 return -1;
1572 }
1573
bcd3f11d
GH
1574 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_CSC_RANGE,
1575 csc_range)) {
1576 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail", __func__,
1577 csc_range);
1578 return -1;
1579 }
1580
70007c4e
JC
1581 /* set src format :GSC video dev*/
1582 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1583 fmt.fmt.pix_mp.width = gsc_handle->src_img.fw;
1584 fmt.fmt.pix_mp.height = gsc_handle->src_img.fh;
1585 fmt.fmt.pix_mp.pixelformat = src_color_space;
1586 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1587 fmt.fmt.pix_mp.num_planes = src_planes;
e6a0625b 1588
70007c4e 1589 if (exynos_v4l2_s_fmt(gsc_handle->gsc_vd_entity->fd, &fmt) < 0) {
6134b8bb 1590 ALOGE("%s::videodev set format failed", __func__);
70007c4e
JC
1591 return -1;
1592 }
1593
1594 /* set src crop info :GSC video dev*/
1595 crop.type = fmt.type;
1596 crop.c.left = gsc_handle->src_img.x;
1597 crop.c.top = gsc_handle->src_img.y;
1598 crop.c.width = gsc_handle->src_img.w;
1599 crop.c.height = gsc_handle->src_img.h;
1600
1601 if (exynos_v4l2_s_crop(gsc_handle->gsc_vd_entity->fd, &crop) < 0) {
6134b8bb 1602 ALOGE("%s::videodev set crop failed", __func__);
70007c4e
JC
1603 return -1;
1604 }
e6a0625b 1605
70007c4e 1606 reqbuf.type = fmt.type;
776bd695 1607 reqbuf.memory = V4L2_MEMORY_DMABUF;
70007c4e
JC
1608 reqbuf.count = MAX_BUFFERS_GSCALER_OUT;
1609
1610 if (exynos_v4l2_reqbufs(gsc_handle->gsc_vd_entity->fd, &reqbuf) < 0) {
6134b8bb 1611 ALOGE("%s::request buffers failed", __func__);
70007c4e
JC
1612 return -1;
1613 }
e6a0625b
JC
1614
1615 Exynos_gsc_Out();
1616
70007c4e
JC
1617 return 0;
1618}
1619
5f54c51b
BG
1620static int exynos_gsc_out_run(void *handle,
1621 exynos_gsc_img *src_img)
70007c4e
JC
1622{
1623 struct GSC_HANDLE *gsc_handle;
1624 struct v4l2_plane planes[NUM_OF_GSC_PLANES];
1625 struct v4l2_buffer buf;
1626 int32_t src_color_space;
1627 int32_t src_planes;
1628 int i;
1629 unsigned int plane_size[NUM_OF_GSC_PLANES];
70007c4e
JC
1630
1631 gsc_handle = (struct GSC_HANDLE *)handle;
1632 if (handle == NULL) {
6134b8bb 1633 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1634 return -1;
1635 }
1636
5f54c51b
BG
1637 /* All buffers have been queued, dequeue one */
1638 if (gsc_handle->src.qbuf_cnt == MAX_BUFFERS_GSCALER_OUT) {
1639 memset(&buf, 0, sizeof(struct v4l2_buffer));
1640 for (i = 0; i < MAX_BUFFERS_GSCALER_OUT; i++)
1641 memset(&planes[i], 0, sizeof(struct v4l2_plane));
1642
1643 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1644 buf.memory = V4L2_MEMORY_DMABUF;
1645 buf.length = src_planes;
1646 buf.m.planes = planes;
1647
1648 if (exynos_v4l2_dqbuf(gsc_handle->gsc_vd_entity->fd, &buf) < 0) {
1649 ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)", __func__,
1650 gsc_handle->src.src_buf_idx, MAX_BUFFERS_GSCALER_OUT);
1651 return -1;
1652 }
1653 gsc_handle->src.qbuf_cnt--;
1654 }
1655
70007c4e
JC
1656 memset(&buf, 0, sizeof(struct v4l2_buffer));
1657 for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1658 memset(&planes[i], 0, sizeof(struct v4l2_plane));
1659
1660 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc_handle->src_img.format);
1661 src_planes = get_yuv_planes(src_color_space);
1662 src_planes = (src_planes == -1) ? 1 : src_planes;
1663
1664 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
776bd695 1665 buf.memory = V4L2_MEMORY_DMABUF;
5f54c51b 1666 buf.flags = V4L2_BUF_FLAG_USE_SYNC;
70007c4e
JC
1667 buf.length = src_planes;
1668 buf.index = gsc_handle->src.src_buf_idx;
1669 buf.m.planes = planes;
5f54c51b 1670 buf.reserved = src_img->acquireFenceFd;
70007c4e 1671
5f54c51b
BG
1672 gsc_handle->src.addr[0] = src_img->yaddr;
1673 gsc_handle->src.addr[1] = src_img->uaddr;
1674 gsc_handle->src.addr[2] = src_img->vaddr;
70007c4e
JC
1675
1676 if (get_plane_size(src_color_space, plane_size,
1677 gsc_handle->src_img.fw * gsc_handle->src_img.fh, src_planes) != true) {
6134b8bb 1678 ALOGE("%s:get_plane_size:fail", __func__);
70007c4e
JC
1679 return -1;
1680 }
1681
1682 for (i = 0; i < buf.length; i++) {
776bd695 1683 buf.m.planes[i].m.fd = (int)gsc_handle->src.addr[i];
70007c4e
JC
1684 buf.m.planes[i].length = plane_size[i];
1685 buf.m.planes[i].bytesused = plane_size[i];
70007c4e
JC
1686 }
1687
1688 /* Queue the buf */
1689 if (exynos_v4l2_qbuf(gsc_handle->gsc_vd_entity->fd, &buf) < 0) {
6134b8bb 1690 ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)", __func__,
70007c4e
JC
1691 gsc_handle->src.src_buf_idx, MAX_BUFFERS_GSCALER_OUT);
1692 return -1;
1693 }
1694 gsc_handle->src.src_buf_idx++;
5f54c51b 1695 gsc_handle->src.src_buf_idx = gsc_handle->src.src_buf_idx % MAX_BUFFERS_GSCALER_OUT;
70007c4e
JC
1696 gsc_handle->src.qbuf_cnt++;
1697
1698 if (gsc_handle->src.stream_on == false) {
5f54c51b
BG
1699 if (exynos_v4l2_streamon(gsc_handle->gsc_vd_entity->fd, buf.type) < 0) {
1700 ALOGE("%s::stream on failed", __func__);
1701 return -1;
70007c4e 1702 }
5f54c51b 1703 gsc_handle->src.stream_on = true;
70007c4e 1704 }
e6a0625b 1705
5f54c51b
BG
1706 src_img->releaseFenceFd = buf.reserved;
1707 return 0;
70007c4e
JC
1708}
1709
1710int exynos_gsc_out_stop(void *handle)
1711{
1712 struct GSC_HANDLE *gsc_handle;
1713 struct v4l2_requestbuffers reqbuf;
1714 struct v4l2_buffer buf;
1715 struct v4l2_plane planes[NUM_OF_GSC_PLANES];
1716 int i;
1717
e6a0625b
JC
1718 Exynos_gsc_In();
1719
70007c4e 1720 gsc_handle = (struct GSC_HANDLE *)handle;
70007c4e 1721 if (handle == NULL) {
6134b8bb 1722 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1723 return -1;
1724 }
e6a0625b 1725
5f54c51b
BG
1726 if (gsc_handle->src.stream_on == true) {
1727 if (exynos_v4l2_streamoff(gsc_handle->gsc_vd_entity->fd,
1728 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
1729 ALOGE("%s::stream off failed", __func__);
1730 return -1;
1731 }
1732 gsc_handle->src.stream_on = false;
70007c4e 1733 }
5f54c51b 1734
70007c4e
JC
1735 gsc_handle->src.src_buf_idx = 0;
1736 gsc_handle->src.qbuf_cnt = 0;
70007c4e 1737
70007c4e 1738 reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
776bd695 1739 reqbuf.memory = V4L2_MEMORY_DMABUF;
70007c4e
JC
1740 reqbuf.count = 0;
1741
1742 if (exynos_v4l2_reqbufs(gsc_handle->gsc_vd_entity->fd, &reqbuf) < 0) {
6134b8bb 1743 ALOGE("%s::request buffers failed", __func__);
70007c4e
JC
1744 return -1;
1745 }
e6a0625b
JC
1746
1747 Exynos_gsc_Out();
1748
70007c4e
JC
1749 return 0;
1750}
1751
7b062be7 1752static int exynos_gsc_m2m_run_core(void *handle)
70007c4e
JC
1753{
1754 struct GSC_HANDLE *gsc_handle;
33aa35f1
DZ
1755 bool is_dirty;
1756 bool is_drm;
7b062be7 1757
70007c4e
JC
1758 gsc_handle = (struct GSC_HANDLE *)handle;
1759
e6a0625b
JC
1760 Exynos_gsc_In();
1761
70007c4e 1762 if (handle == NULL) {
6134b8bb 1763 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
1764 return -1;
1765 }
1766
33aa35f1
DZ
1767 is_dirty = gsc_handle->src.dirty || gsc_handle->dst.dirty;
1768 is_drm = gsc_handle->src.mode_drm;
1769
1770 if (is_dirty && (gsc_handle->src.mode_drm != gsc_handle->dst.mode_drm)) {
1771 ALOGE("%s: drm mode mismatch between src and dst, gsc%d (s=%d d=%d)",
1772 __func__, gsc_handle->gsc_id, gsc_handle->src.mode_drm,
1773 gsc_handle->dst.mode_drm);
1774 return -1;
1775 } else if (is_drm && !gsc_handle->allow_drm) {
1776 ALOGE("%s: drm mode is not supported on gsc%d", __func__,
1777 gsc_handle->gsc_id);
1778 return -1;
1779 }
e76fa944
RSZ
1780
1781 if (m_exynos_gsc_check_src_size(&gsc_handle->src.width, &gsc_handle->src.height,
1782 &gsc_handle->src.crop_left, &gsc_handle->src.crop_top,
1783 &gsc_handle->src.crop_width, &gsc_handle->src.crop_height,
1784 gsc_handle->src.v4l2_colorformat) == false) {
1785 ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__);
33aa35f1 1786 return -1;
e76fa944
RSZ
1787 }
1788
1789 if (m_exynos_gsc_check_dst_size(&gsc_handle->dst.width, &gsc_handle->dst.height,
1790 &gsc_handle->dst.crop_left, &gsc_handle->dst.crop_top,
1791 &gsc_handle->dst.crop_width, &gsc_handle->dst.crop_height,
1792 gsc_handle->dst.v4l2_colorformat,
1793 gsc_handle->dst.rotation) == false) {
1794 ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__);
33aa35f1 1795 return -1;
5f18f784 1796 }
70007c4e 1797
33aa35f1
DZ
1798 /* dequeue buffers from previous work if necessary */
1799 if (gsc_handle->src.stream_on == true) {
1800 if (exynos_gsc_m2m_wait_frame_done(handle) < 0) {
1801 ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__);
1802 return -1;
1803 }
1804 }
1805
1806 /*
1807 * need to set the content protection flag before doing reqbufs
1808 * in set_format
1809 */
1810 if (is_dirty && gsc_handle->allow_drm && is_drm) {
1811 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_fd,
1812 V4L2_CID_CONTENT_PROTECTION, is_drm) < 0) {
1813 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
1814 return -1;
1815 }
1816 }
1817
1818 /*
1819 * from this point on, we have to ensure to call stop to clean up whatever
1820 * state we have set.
1821 */
1822
e2426aa8
GH
1823 if (gsc_handle->src.dirty) {
1824 if (m_exynos_gsc_set_format(gsc_handle->gsc_fd, &gsc_handle->src) == false) {
1825 ALOGE("%s::m_exynos_gsc_set_format(src) fail", __func__);
1826 goto done;
1827 }
1828 gsc_handle->src.dirty = false;
5f18f784 1829 }
70007c4e 1830
e2426aa8
GH
1831 if (gsc_handle->dst.dirty) {
1832 if (m_exynos_gsc_set_format(gsc_handle->gsc_fd, &gsc_handle->dst) == false) {
1833 ALOGE("%s::m_exynos_gsc_set_format(dst) fail", __func__);
1834 goto done;
1835 }
1836 gsc_handle->dst.dirty = false;
5f18f784 1837 }
70007c4e 1838
33aa35f1
DZ
1839 /* if we are enabling drm, make sure to enable hw protection.
1840 * Need to do this before queuing buffers so that the mmu is reserved
1841 * and power domain is kept on.
1842 */
1843 if (is_dirty && gsc_handle->allow_drm && is_drm) {
1844 unsigned int protect_id = 0;
1845
1846 if (gsc_handle->gsc_id == 0) {
1847 protect_id = CP_PROTECT_GSC0;
1848 } else if (gsc_handle->gsc_id == 3) {
1849 protect_id = CP_PROTECT_GSC3;
1850 } else {
1851 ALOGE("%s::invalid gscaler id %d for content protection", __func__,
1852 gsc_handle->gsc_id);
1853 goto done;
1854 }
1855
1856 if (CP_Enable_Path_Protection(protect_id) != 0) {
1857 ALOGE("%s::CP_Enable_Path_Protection failed", __func__);
9f6d8287
BG
1858 goto done;
1859 }
33aa35f1 1860 gsc_handle->protection_enabled = true;
9f6d8287
BG
1861 }
1862
5f18f784
SK
1863 if (m_exynos_gsc_set_addr(gsc_handle->gsc_fd, &gsc_handle->src) == false) {
1864 ALOGE("%s::m_exynos_gsc_set_addr(src) fail", __func__);
1865 goto done;
1866 }
70007c4e 1867
5f18f784
SK
1868 if (m_exynos_gsc_set_addr(gsc_handle->gsc_fd, &gsc_handle->dst) == false) {
1869 ALOGE("%s::m_exynos_gsc_set_addr(dst) fail", __func__);
1870 goto done;
70007c4e
JC
1871 }
1872
1873 if (gsc_handle->src.stream_on == false) {
1874 if (exynos_v4l2_streamon(gsc_handle->gsc_fd, gsc_handle->src.buf_type) < 0) {
6134b8bb 1875 ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
70007c4e
JC
1876 goto done;
1877 }
1878 gsc_handle->src.stream_on = true;
1879 }
1880
1881 if (gsc_handle->dst.stream_on == false) {
1882 if (exynos_v4l2_streamon(gsc_handle->gsc_fd, gsc_handle->dst.buf_type) < 0) {
6134b8bb 1883 ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
70007c4e
JC
1884 goto done;
1885 }
1886 gsc_handle->dst.stream_on = true;
1887 }
1888
7b062be7
YS
1889 Exynos_gsc_Out();
1890
1891 return 0;
1892
1893done:
33aa35f1 1894 exynos_gsc_m2m_stop(handle);
7b062be7
YS
1895 return -1;
1896}
1897
1898static int exynos_gsc_m2m_wait_frame_done(void *handle)
1899{
1900 struct GSC_HANDLE *gsc_handle;
7b062be7
YS
1901
1902 gsc_handle = (struct GSC_HANDLE *)handle;
1903
1904 Exynos_gsc_In();
1905
1906 if (handle == NULL) {
1907 ALOGE("%s::handle == NULL() fail", __func__);
1908 return -1;
1909 }
1910
1911 if ((gsc_handle->src.stream_on == false) || (gsc_handle->dst.stream_on == false)) {
1912 ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
1913 return -1;
1914 }
1915
9f6d8287
BG
1916 if (gsc_handle->src.buffer_queued) {
1917 if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->src.buffer) < 0) {
1918 ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
1919 return -1;
1920 }
1921 gsc_handle->src.buffer_queued = false;
70007c4e
JC
1922 }
1923
9f6d8287
BG
1924 if (gsc_handle->dst.buffer_queued) {
1925 if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->dst.buffer) < 0) {
1926 ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
1927 return -1;
1928 }
1929 gsc_handle->dst.buffer_queued = false;
7b062be7
YS
1930 }
1931
43b5926c
GH
1932 Exynos_gsc_Out();
1933
1934 return 0;
1935}
1936
1937static int exynos_gsc_m2m_stop(void *handle)
1938{
1939 struct GSC_HANDLE *gsc_handle;
1940 struct v4l2_requestbuffers req_buf;
33aa35f1 1941 int ret = 0;
43b5926c
GH
1942
1943 gsc_handle = (struct GSC_HANDLE *)handle;
1944
1945 Exynos_gsc_In();
1946
33aa35f1
DZ
1947 if (!gsc_handle->src.stream_on && !gsc_handle->dst.stream_on) {
1948 /* wasn't streaming, return success */
1949 return 0;
1950 } else if (gsc_handle->src.stream_on != gsc_handle->dst.stream_on) {
1951 ALOGE("%s: invalid state, queue stream state doesn't match (%d != %d)",
1952 __func__, gsc_handle->src.stream_on, gsc_handle->dst.stream_on);
1953 ret = -1;
1954 }
1955
1956 /*
1957 * we need to plow forward on errors below to make sure that if we had
1958 * turned on content protection on secure side, we turn it off.
1959 *
1960 * also, if we only failed to turn on one of the streams, we'll turn
1961 * the other one off correctly.
1962 */
1963 if (gsc_handle->src.stream_on == true) {
1964 if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->src.buf_type) < 0) {
1965 ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
1966 ret = -1;
1967 }
1968 gsc_handle->src.stream_on = false;
7b062be7 1969 }
7b062be7 1970
33aa35f1
DZ
1971
1972 if (gsc_handle->dst.stream_on == true) {
1973 if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->dst.buf_type) < 0) {
1974 ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
1975 ret = -1;
1976 }
1977 gsc_handle->dst.stream_on = false;
1978 }
1979
1980 /* if drm is enabled */
1981 if (gsc_handle->allow_drm && gsc_handle->protection_enabled) {
1982 unsigned int protect_id = 0;
1983
1984 if (gsc_handle->gsc_id == 0)
1985 protect_id = CP_PROTECT_GSC0;
1986 else if (gsc_handle->gsc_id == 3)
1987 protect_id = CP_PROTECT_GSC3;
1988
1989 CP_Disable_Path_Protection(protect_id);
1990 gsc_handle->protection_enabled = false;
1991 }
1992
1993 if (exynos_v4l2_s_ctrl(gsc_handle->gsc_fd,
1994 V4L2_CID_CONTENT_PROTECTION, 0) < 0) {
1995 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
1996 __func__);
1997 ret = -1;
7b062be7 1998 }
7b062be7
YS
1999
2000 /* src: clear_buf */
2001 req_buf.count = 0;
2002 req_buf.type = gsc_handle->src.buf_type;
2003 req_buf.memory = V4L2_MEMORY_DMABUF;
2004 if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
2005 ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
33aa35f1 2006 ret = -1;
7b062be7
YS
2007 }
2008
2009 /* dst: clear_buf */
2010 req_buf.count = 0;
2011 req_buf.type = gsc_handle->dst.buf_type;
2012 req_buf.memory = V4L2_MEMORY_DMABUF;
2013 if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
2014 ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
33aa35f1 2015 ret = -1;
7b062be7
YS
2016 }
2017
2018 Exynos_gsc_Out();
2019
33aa35f1 2020 return ret;
7b062be7
YS
2021}
2022
2023int exynos_gsc_convert(
2024 void *handle)
2025{
2026 struct GSC_HANDLE *gsc_handle;
2027 int ret = -1;
2028 gsc_handle = (struct GSC_HANDLE *)handle;
2029
2030 Exynos_gsc_In();
2031
2032 if (handle == NULL) {
2033 ALOGE("%s::handle == NULL() fail", __func__);
2034 return -1;
2035 }
2036
2037 exynos_mutex_lock(gsc_handle->op_mutex);
2038
2039 if (gsc_handle->flag_local_path == true) {
2040 ALOGE("%s::this exynos_gsc is connected by another hw internaly. So, don't call exynos_gsc_convert()", __func__);
2041 goto done;
2042 }
2043
2044 if (exynos_gsc_m2m_run_core(handle) < 0) {
2045 ALOGE("%s::exynos_gsc_run_core fail", __func__);
2046 goto done;
2047 }
2048
2049 if (exynos_gsc_m2m_wait_frame_done(handle) < 0) {
2050 ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
70007c4e
JC
2051 goto done;
2052 }
2053
9f6d8287
BG
2054 if (gsc_handle->src.releaseFenceFd >= 0) {
2055 close(gsc_handle->src.releaseFenceFd);
2056 gsc_handle->src.releaseFenceFd = -1;
2057 }
2058
2059 if (gsc_handle->dst.releaseFenceFd >= 0) {
2060 close(gsc_handle->dst.releaseFenceFd);
2061 gsc_handle->dst.releaseFenceFd = -1;
2062 }
2063
43b5926c
GH
2064 if (exynos_gsc_m2m_stop(handle) < 0) {
2065 ALOGE("%s::exynos_gsc_m2m_stop", __func__);
2066 goto done;
2067 }
2068
70007c4e
JC
2069 ret = 0;
2070
2071done:
2072 if (gsc_handle->flag_exclusive_open == false) {
2073 if (gsc_handle->flag_local_path == false)
2074 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
2075 }
2076
2077 exynos_mutex_unlock(gsc_handle->op_mutex);
2078
e6a0625b
JC
2079 Exynos_gsc_Out();
2080
70007c4e
JC
2081 return ret;
2082}
2083
e6a0625b
JC
2084int exynos_gsc_m2m_run(void *handle,
2085 exynos_gsc_img *src_img,
2086 exynos_gsc_img *dst_img)
2087{
9f6d8287 2088 struct GSC_HANDLE *gsc_handle = handle;
e6a0625b
JC
2089 void *addr[3] = {NULL, NULL, NULL};
2090 int ret = 0;
2091
2092 Exynos_gsc_In();
2093
2094 addr[0] = (void *)src_img->yaddr;
2095 addr[1] = (void *)src_img->uaddr;
2096 addr[2] = (void *)src_img->vaddr;
9f6d8287 2097 ret = exynos_gsc_set_src_addr(handle, addr, src_img->acquireFenceFd);
e6a0625b
JC
2098 if (ret < 0) {
2099 ALOGE("%s::fail: exynos_gsc_set_src_addr[%x %x %x]", __func__,
2100 (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]);
7b062be7 2101 return -1;
e6a0625b
JC
2102 }
2103
2104 addr[0] = (void *)dst_img->yaddr;
2105 addr[1] = (void *)dst_img->uaddr;
2106 addr[2] = (void *)dst_img->vaddr;
9f6d8287 2107 ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->acquireFenceFd);
e6a0625b
JC
2108 if (ret < 0) {
2109 ALOGE("%s::fail: exynos_gsc_set_dst_addr[%x %x %x]", __func__,
2110 (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]);
7b062be7 2111 return -1;
e6a0625b
JC
2112 }
2113
7b062be7 2114 ret = exynos_gsc_m2m_run_core(handle);
e6a0625b 2115 if (ret < 0) {
7b062be7
YS
2116 ALOGE("%s::fail: exynos_gsc_m2m_run_core", __func__);
2117 return -1;
e6a0625b
JC
2118 }
2119
de5fb8ee
BG
2120 if (src_img->acquireFenceFd >= 0) {
2121 close(src_img->acquireFenceFd);
2122 src_img->acquireFenceFd = -1;
2123 }
2124
2125 if (dst_img->acquireFenceFd >= 0) {
2126 close(dst_img->acquireFenceFd);
2127 dst_img->acquireFenceFd = -1;
2128 }
2129
9f6d8287
BG
2130 src_img->releaseFenceFd = gsc_handle->src.releaseFenceFd;
2131 dst_img->releaseFenceFd = gsc_handle->dst.releaseFenceFd;
2132
e6a0625b
JC
2133 Exynos_gsc_Out();
2134
2135 return 0;
2136}
2137
70007c4e 2138int exynos_gsc_config_exclusive(void *handle,
e6a0625b
JC
2139 exynos_gsc_img *src_img,
2140 exynos_gsc_img *dst_img)
70007c4e 2141{
e6a0625b
JC
2142
2143 Exynos_gsc_In();
2144
70007c4e
JC
2145 struct GSC_HANDLE *gsc_handle;
2146 int ret = 0;
2147 gsc_handle = (struct GSC_HANDLE *)handle;
70007c4e 2148 if (handle == NULL) {
6134b8bb 2149 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
2150 return -1;
2151 }
2152
2153 switch (gsc_handle->gsc_mode) {
2154 case GSC_M2M_MODE:
e6a0625b 2155 ret = exynos_gsc_m2m_config(handle, src_img, dst_img);
70007c4e
JC
2156 break;
2157 case GSC_OUTPUT_MODE:
2158 ret = exynos_gsc_out_config(handle, src_img, dst_img);
2159 break;
2160 case GSC_CAPTURE_MODE:
2161 //to do
2162 break;
2163 default:
2164 break;
2165 }
e6a0625b
JC
2166
2167 Exynos_gsc_Out();
2168
70007c4e
JC
2169 return ret;
2170
2171}
2172
2173int exynos_gsc_run_exclusive(void *handle,
e6a0625b
JC
2174 exynos_gsc_img *src_img,
2175 exynos_gsc_img *dst_img)
70007c4e
JC
2176{
2177 struct GSC_HANDLE *gsc_handle;
2178 int ret = 0;
7b062be7
YS
2179
2180 Exynos_gsc_In();
2181
70007c4e 2182 gsc_handle = (struct GSC_HANDLE *)handle;
70007c4e 2183 if (handle == NULL) {
6134b8bb 2184 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
2185 return -1;
2186 }
2187
2188 switch (gsc_handle->gsc_mode) {
2189 case GSC_M2M_MODE:
e6a0625b 2190 ret = exynos_gsc_m2m_run(handle, src_img, dst_img);
70007c4e
JC
2191 break;
2192 case GSC_OUTPUT_MODE:
5f54c51b 2193 ret = exynos_gsc_out_run(handle, src_img);
70007c4e
JC
2194 break;
2195 case GSC_CAPTURE_MODE:
2196 //to do
2197 break;
2198 default:
2199 break;
2200 }
7b062be7
YS
2201
2202 Exynos_gsc_Out();
2203
70007c4e
JC
2204 return ret;
2205}
2206
43b5926c
GH
2207int exynos_gsc_wait_frame_done_exclusive(void *handle)
2208{
2209 struct GSC_HANDLE *gsc_handle;
2210 int ret = 0;
2211 gsc_handle = (struct GSC_HANDLE *)handle;
2212
2213 Exynos_gsc_In();
2214
2215 if (handle == NULL) {
2216 ALOGE("%s::handle == NULL() fail", __func__);
2217 return -1;
2218 }
2219
2220 if (gsc_handle->gsc_mode == GSC_M2M_MODE)
2221 ret = exynos_gsc_m2m_wait_frame_done(handle);
2222
2223 Exynos_gsc_Out();
2224
2225 return ret;
2226}
2227
70007c4e
JC
2228int exynos_gsc_stop_exclusive(void *handle)
2229{
2230 struct GSC_HANDLE *gsc_handle;
2231 int ret = 0;
2232 gsc_handle = (struct GSC_HANDLE *)handle;
e6a0625b
JC
2233
2234 Exynos_gsc_In();
2235
70007c4e 2236 if (handle == NULL) {
6134b8bb 2237 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
2238 return -1;
2239 }
2240
2241 switch (gsc_handle->gsc_mode) {
2242 case GSC_M2M_MODE:
43b5926c 2243 ret = exynos_gsc_m2m_stop(handle);
70007c4e
JC
2244 break;
2245 case GSC_OUTPUT_MODE:
2246 ret = exynos_gsc_out_stop(handle);
2247 break;
2248 case GSC_CAPTURE_MODE:
2249 //to do
2250 break;
2251 default:
e6a0625b 2252 break;
70007c4e 2253 }
e6a0625b
JC
2254
2255 Exynos_gsc_Out();
2256
70007c4e 2257 return ret;
70007c4e
JC
2258}
2259
70007c4e
JC
2260int exynos_gsc_connect(
2261 void *handle,
2262 void *hw)
2263{
2264 struct GSC_HANDLE *gsc_handle;
2265 int ret = -1;
2266 gsc_handle = (struct GSC_HANDLE *)handle;
2267
e6a0625b
JC
2268 Exynos_gsc_In();
2269
70007c4e 2270 if (handle == NULL) {
6134b8bb 2271 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
2272 return -1;
2273 }
2274
2275 exynos_mutex_lock(gsc_handle->op_mutex);
2276
2277 gsc_handle->flag_local_path = true;
2278
2279 if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == false) {
2280 if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle) == false) {
6134b8bb 2281 ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__);
70007c4e
JC
2282 goto done;
2283 }
2284 }
2285
2286 ret = 0;
2287
e6a0625b
JC
2288 Exynos_gsc_Out();
2289
70007c4e
JC
2290done:
2291 exynos_mutex_unlock(gsc_handle->op_mutex);
2292
2293 return ret;
2294}
2295
2296int exynos_gsc_disconnect(
2297 void *handle,
2298 void *hw)
2299{
2300 struct GSC_HANDLE *gsc_handle;
2301 gsc_handle = (struct GSC_HANDLE *)handle;
2302
e6a0625b
JC
2303 Exynos_gsc_In();
2304
70007c4e 2305 if (handle == NULL) {
6134b8bb 2306 ALOGE("%s::handle == NULL() fail", __func__);
70007c4e
JC
2307 return -1;
2308 }
2309
2310 exynos_mutex_lock(gsc_handle->op_mutex);
2311
2312 gsc_handle->flag_local_path = false;
2313
2314 exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
2315
2316 exynos_mutex_unlock(gsc_handle->op_mutex);
2317
e6a0625b
JC
2318 Exynos_gsc_Out();
2319
70007c4e
JC
2320 return 0;
2321}