2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright@ Samsung Electronics Co. LTD
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \file exynos_gscaler.c
20 * \brief header file for Gscaler HAL
21 * \author ShinWon Lee (shinwon.lee@samsung.com)
24 * <b>Revision History: </b>
25 * - 2012.01.09 : ShinWon Lee(shinwon.lee@samsung.com) \n
28 * - 2012.02.07 : ShinWon Lee(shinwon.lee@samsung.com) \n
29 * Change file name to exynos_gscaler.h
31 * - 2012.02.09 : Sangwoo, Parkk(sw5771.park@samsung.com) \n
32 * Use Multiple Gscaler by Multiple Process
34 * - 2012.02.20 : Sangwoo, Park(sw5771.park@samsung.com) \n
35 * Add exynos_gsc_set_rotation() API
37 * - 2012.02.20 : ShinWon Lee(shinwon.lee@samsung.com) \n
42 //#define LOG_NDEBUG 0
43 #include "exynos_gsc_utils.h"
44 #include "content_protect.h"
46 static int exynos_gsc_m2m_wait_frame_done(void *handle
);
47 static int exynos_gsc_m2m_stop(void *handle
);
49 static unsigned int m_gsc_get_plane_count(
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
:
63 case V4L2_PIX_FMT_NV16
:
64 case V4L2_PIX_FMT_NV61
:
67 case V4L2_PIX_FMT_NV12M
:
68 case V4L2_PIX_FMT_NV12MT_16X16
:
69 case V4L2_PIX_FMT_NV12
:
70 case V4L2_PIX_FMT_NV21
:
71 case V4L2_PIX_FMT_NV21M
:
74 case V4L2_PIX_FMT_YVU420M
:
75 case V4L2_PIX_FMT_YUV422P
:
76 case V4L2_PIX_FMT_YUV420M
:
80 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
81 __func__
, v4l_pixel_format
);
89 static unsigned int m_gsc_get_plane_size(
90 unsigned int *plane_size
,
95 switch (v4l_pixel_format
) {
97 case V4L2_PIX_FMT_RGB32
:
98 case V4L2_PIX_FMT_BGR32
:
99 plane_size
[0] = width
* height
* 4;
103 case V4L2_PIX_FMT_RGB24
:
104 plane_size
[0] = width
* height
* 3;
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;
118 case V4L2_PIX_FMT_NV12M
:
119 case V4L2_PIX_FMT_NV12
:
120 case V4L2_PIX_FMT_NV21
:
121 case V4L2_PIX_FMT_NV21M
:
122 plane_size
[0] = width
* height
;
123 plane_size
[1] = width
* (height
/ 2);
126 case V4L2_PIX_FMT_NV16
:
127 case V4L2_PIX_FMT_NV61
:
128 plane_size
[0] = width
* height
* 2;
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);
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);
145 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
146 __func__
, v4l_pixel_format
);
154 static int m_exynos_gsc_multiple_of_n(
168 result
= (number
- (number
& (N
-1)));
171 result
= number
- (number
% N
);
177 static 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
)
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
);
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
);
195 switch (v4l2_colorformat
) {
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);
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
:
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);
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
:
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);
240 static 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
,
249 unsigned int *new_crop_w
;
250 unsigned int *new_crop_h
;
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
);
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
);
269 switch (v4l2_colorformat
) {
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);
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);
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
:
303 static int m_exynos_gsc_output_create(
304 struct GSC_HANDLE
*gsc_handle
,
308 struct media_device
*media0
;
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
;
321 if ((out_mode
!= GSC_OUT_FIMD
) &&
322 (out_mode
!= GSC_OUT_TV
))
325 gsc_handle
->out_mode
= out_mode
;
326 /* GSCX => FIMD_WINX : arbitrary linking is not allowed */
327 if ((out_mode
== GSC_OUT_FIMD
) &&
332 sprintf(node
, "%s%d", PFX_NODE_MEDIADEV
, 0);
333 media0
= exynos_media_open(node
);
334 if (media0
== NULL
) {
335 ALOGE("%s::exynos_media_open failed (node=%s)", __func__
, node
);
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
);
343 sprintf(devname
, PFX_MXR_ENTITY
, 0);
345 sink_sd_entity
= exynos_media_get_entity_by_name(media0
, devname
, strlen(devname
));
346 sink_sd_entity
->fd
= exynos_subdev_open_devname(devname
, O_RDWR
);
347 if ( sink_sd_entity
->fd
< 0) {
348 ALOGE("%s:: failed to open sink subdev node", __func__
);
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
));
356 sprintf(devname
, PFX_GSC_SUBDEV_ENTITY
, dev_num
);
357 gsc_sd_entity
= exynos_media_get_entity_by_name(media0
, devname
, strlen(devname
));
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
);
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
];
368 links
->source
->entity
!= gsc_vd_entity
||
369 links
->sink
->entity
!= gsc_sd_entity
) {
371 } else if (exynos_media_setup_link(media0
, links
->source
, links
->sink
, MEDIA_LNK_FL_ENABLED
) < 0) {
372 ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
373 __func__
, links
->source
->entity
->info
.id
, links
->sink
->entity
->info
.id
);
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
];
382 if (links
== NULL
|| links
->source
->entity
!= gsc_sd_entity
||
383 links
->sink
->entity
!= sink_sd_entity
) {
385 } else if (exynos_media_setup_link(media0
, links
->source
, links
->sink
, MEDIA_LNK_FL_ENABLED
) < 0) {
386 ALOGE("%s::exynos_media_setup_link [src.entity=%d->sink.entity=%d] failed",
387 __func__
, links
->source
->entity
->info
.id
, links
->sink
->entity
->info
.id
);
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
;
398 if (exynos_v4l2_querycap(gsc_vd_entity
->fd
, cap
) == false) {
399 ALOGE("%s::exynos_v4l2_querycap() fail", __func__
);
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
;
405 gsc_handle
->media0
= media0
;
417 static int m_exynos_gsc_m2m_create(
429 video_node_num
= NODE_NUM_GSC_0
;
432 video_node_num
= NODE_NUM_GSC_1
;
435 video_node_num
= NODE_NUM_GSC_2
;
438 video_node_num
= NODE_NUM_GSC_3
;
441 ALOGE("%s::unexpected dev(%d) fail", __func__
, dev
);
446 sprintf(node
, "%s%d", PFX_NODE_GSC
, video_node_num
);
447 fd
= exynos_v4l2_open(node
, O_RDWR
);
449 ALOGE("%s::exynos_v4l2_open(%s) fail", __func__
, node
);
453 cap
= V4L2_CAP_STREAMING
|
454 V4L2_CAP_VIDEO_OUTPUT_MPLANE
|
455 V4L2_CAP_VIDEO_CAPTURE_MPLANE
;
457 if (exynos_v4l2_querycap(fd
, cap
) == false) {
458 ALOGE("%s::exynos_v4l2_querycap() fail", __func__
);
471 static bool m_exynos_gsc_out_destroy(struct GSC_HANDLE
*gsc_handle
)
473 struct media_link
* links
;
478 if (gsc_handle
== NULL
) {
479 ALOGE("%s::gsc_handle is NULL", __func__
);
483 if (gsc_handle
->src
.stream_on
== true) {
484 if (exynos_gsc_out_stop((void *)gsc_handle
) < 0)
485 ALOGE("%s::exynos_gsc_out_stop() fail", __func__
);
487 gsc_handle
->src
.stream_on
= false;
490 /* unlink : gscaler-out --> fimd */
491 for (i
= 0; i
< (int) gsc_handle
->gsc_sd_entity
->num_links
; i
++) {
492 links
= &gsc_handle
->gsc_sd_entity
->links
[i
];
494 if (links
== NULL
|| links
->source
->entity
!= gsc_handle
->gsc_sd_entity
||
495 links
->sink
->entity
!= gsc_handle
->sink_sd_entity
) {
497 } else if (exynos_media_setup_link(gsc_handle
->media0
, links
->source
,
498 links
->sink
, 0) < 0) {
499 ALOGE("%s::exynos_media_setup_unlink [src.entity=%d->sink.entity=%d] failed",
500 __func__
, links
->source
->entity
->info
.id
, links
->sink
->entity
->info
.id
);
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;
515 static bool m_exynos_gsc_destroy(
516 struct GSC_HANDLE
*gsc_handle
)
520 /* just in case, we call stop here because we cannot afford to leave
521 * secure side protection on if things failed.
523 exynos_gsc_m2m_stop(gsc_handle
);
525 if (0 < gsc_handle
->gsc_fd
)
526 close(gsc_handle
->gsc_fd
);
527 gsc_handle
->gsc_fd
= 0;
534 bool m_exynos_gsc_find_and_trylock_and_create(
535 struct GSC_HANDLE
*gsc_handle
)
538 bool flag_find_new_gsc
= false;
539 unsigned int total_sleep_time
= 0;
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()
547 if (i
== 0 || i
== 3)
550 if (exynos_mutex_trylock(gsc_handle
->obj_mutex
[i
]) == true) {
553 m_exynos_gsc_destroy(gsc_handle
);
556 gsc_handle
->gsc_id
= i
;
557 gsc_handle
->gsc_fd
= m_exynos_gsc_m2m_create(i
);
558 if (gsc_handle
->gsc_fd
< 0) {
559 gsc_handle
->gsc_fd
= 0;
560 exynos_mutex_unlock(gsc_handle
->obj_mutex
[i
]);
564 /* Trade temporary object for one in the pool */
565 if (gsc_handle
->cur_obj_mutex
) {
566 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
567 if (gsc_handle
->destroy_cur_obj_mutex
)
568 exynos_mutex_destroy(gsc_handle
->cur_obj_mutex
);
571 gsc_handle
->destroy_cur_obj_mutex
= false;
572 gsc_handle
->cur_obj_mutex
= gsc_handle
->obj_mutex
[i
];
574 flag_find_new_gsc
= true;
579 // waiting for another process doesn't use gscaler.
580 // we need to make decision how to do.
581 if (flag_find_new_gsc
== false) {
582 usleep(GSC_WAITING_TIME_FOR_TRYLOCK
);
583 total_sleep_time
+= GSC_WAITING_TIME_FOR_TRYLOCK
;
584 ALOGV("%s::waiting for anthere process doens't use gscaler", __func__
);
587 } while( flag_find_new_gsc
== false
588 && total_sleep_time
< MAX_GSC_WAITING_TIME_FOR_TRYLOCK
);
590 if (flag_find_new_gsc
== false)
591 ALOGE("%s::we don't have no available gsc.. fail", __func__
);
595 return flag_find_new_gsc
;
598 static bool m_exynos_gsc_set_format(
600 struct gsc_info
*info
)
604 struct v4l2_requestbuffers req_buf
;
607 plane_count
= m_gsc_get_plane_count(info
->v4l2_colorformat
);
608 if (plane_count
< 0) {
609 ALOGE("%s::not supported v4l2_colorformat", __func__
);
613 if (exynos_v4l2_s_ctrl(fd
, V4L2_CID_ROTATE
, info
->rotation
) < 0) {
614 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__
);
618 if (exynos_v4l2_s_ctrl(fd
, V4L2_CID_VFLIP
, info
->flip_horizontal
) < 0) {
619 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__
);
623 if (exynos_v4l2_s_ctrl(fd
, V4L2_CID_HFLIP
, info
->flip_vertical
) < 0) {
624 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__
);
628 if (exynos_v4l2_s_ctrl(fd
, V4L2_CID_CSC_RANGE
, info
->csc_range
) < 0) {
629 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__
);
632 info
->format
.type
= info
->buf_type
;
633 info
->format
.fmt
.pix_mp
.width
= info
->width
;
634 info
->format
.fmt
.pix_mp
.height
= info
->height
;
635 info
->format
.fmt
.pix_mp
.pixelformat
= info
->v4l2_colorformat
;
636 info
->format
.fmt
.pix_mp
.field
= V4L2_FIELD_ANY
;
637 info
->format
.fmt
.pix_mp
.num_planes
= plane_count
;
639 if (exynos_v4l2_s_fmt(fd
, &info
->format
) < 0) {
640 ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__
);
644 info
->crop
.type
= info
->buf_type
;
645 info
->crop
.c
.left
= info
->crop_left
;
646 info
->crop
.c
.top
= info
->crop_top
;
647 info
->crop
.c
.width
= info
->crop_width
;
648 info
->crop
.c
.height
= info
->crop_height
;
650 if (exynos_v4l2_s_crop(fd
, &info
->crop
) < 0) {
651 ALOGE("%s::exynos_v4l2_s_crop() fail", __func__
);
655 if (exynos_v4l2_s_ctrl(fd
, V4L2_CID_CACHEABLE
, info
->cacheable
) < 0) {
656 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__
);
661 req_buf
.type
= info
->buf_type
;
662 req_buf
.memory
= V4L2_MEMORY_DMABUF
;
663 if (exynos_v4l2_reqbufs(fd
, &req_buf
) < 0) {
664 ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__
);
673 static bool m_exynos_gsc_set_addr(
675 struct gsc_info
*info
)
678 unsigned int plane_size
[NUM_OF_GSC_PLANES
];
680 m_gsc_get_plane_size(plane_size
,
683 info
->v4l2_colorformat
);
685 info
->buffer
.index
= 0;
686 info
->buffer
.flags
= V4L2_BUF_FLAG_USE_SYNC
;
687 info
->buffer
.type
= info
->buf_type
;
688 info
->buffer
.memory
= V4L2_MEMORY_DMABUF
;
689 info
->buffer
.m
.planes
= info
->planes
;
690 info
->buffer
.length
= info
->format
.fmt
.pix_mp
.num_planes
;
691 info
->buffer
.reserved
= info
->acquireFenceFd
;
693 for (i
= 0; i
< info
->format
.fmt
.pix_mp
.num_planes
; i
++) {
694 info
->buffer
.m
.planes
[i
].m
.fd
= (int)info
->addr
[i
];
695 info
->buffer
.m
.planes
[i
].length
= plane_size
[i
];
696 info
->buffer
.m
.planes
[i
].bytesused
= 0;
699 if (exynos_v4l2_qbuf(fd
, &info
->buffer
) < 0) {
700 ALOGE("%s::exynos_v4l2_qbuf() fail", __func__
);
703 info
->buffer_queued
= true;
705 info
->releaseFenceFd
= info
->buffer
.reserved
;
710 void *exynos_gsc_create(
719 struct GSC_HANDLE
*gsc_handle
= (struct GSC_HANDLE
*)malloc(sizeof(struct GSC_HANDLE
));
720 if (gsc_handle
== NULL
) {
721 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__
);
725 gsc_handle
->gsc_fd
= 0;
726 memset(&gsc_handle
->src
, 0, sizeof(struct gsc_info
));
727 memset(&gsc_handle
->dst
, 0, sizeof(struct gsc_info
));
729 gsc_handle
->src
.buf_type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
730 gsc_handle
->dst
.buf_type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
732 gsc_handle
->op_mutex
= NULL
;
733 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++)
734 gsc_handle
->obj_mutex
[i
] = NULL
;
736 gsc_handle
->cur_obj_mutex
= NULL
;
737 gsc_handle
->destroy_cur_obj_mutex
= false;
738 gsc_handle
->flag_local_path
= false;
739 gsc_handle
->flag_exclusive_open
= false;
742 op_id
= rand() % 1000000; // just make random id
743 sprintf(mutex_name
, "%sOp%d", LOG_TAG
, op_id
);
744 gsc_handle
->op_mutex
= exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE
, mutex_name
);
745 if (gsc_handle
->op_mutex
== NULL
) {
746 ALOGE("%s::exynos_mutex_create(%s) fail", __func__
, mutex_name
);
750 exynos_mutex_lock(gsc_handle
->op_mutex
);
752 // check if it is available
753 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++) {
754 sprintf(mutex_name
, "%sObject%d", LOG_TAG
, i
);
756 gsc_handle
->obj_mutex
[i
] = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED
, mutex_name
);
757 if (gsc_handle
->obj_mutex
[i
] == NULL
) {
758 ALOGE("%s::exynos_mutex_create(%s) fail", __func__
, mutex_name
);
763 if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle
) == false) {
764 ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__
);
768 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
769 exynos_mutex_unlock(gsc_handle
->op_mutex
);
771 return (void *)gsc_handle
;
775 m_exynos_gsc_destroy(gsc_handle
);
777 if (gsc_handle
->cur_obj_mutex
)
778 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
780 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++) {
781 if ((gsc_handle
->obj_mutex
[i
] != NULL
) &&
782 (exynos_mutex_get_created_status(gsc_handle
->obj_mutex
[i
]) == true)) {
783 if (exynos_mutex_destroy(gsc_handle
->obj_mutex
[i
]) == false)
784 ALOGE("%s::exynos_mutex_destroy() fail", __func__
);
788 if (gsc_handle
->op_mutex
)
789 exynos_mutex_unlock(gsc_handle
->op_mutex
);
791 if (exynos_mutex_destroy(gsc_handle
->op_mutex
) == false)
792 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__
);
802 void *exynos_gsc_reserve(int dev_num
)
805 unsigned int total_sleep_time
= 0;
806 bool gsc_flag
= false;
808 if ((dev_num
< 0) || (dev_num
>= NUM_OF_GSC_HW
)) {
809 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__
, dev_num
);
813 struct GSC_HANDLE
*gsc_handle
= (struct GSC_HANDLE
*)malloc(sizeof(struct GSC_HANDLE
));
814 if (gsc_handle
== NULL
) {
815 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__
);
819 gsc_handle
->gsc_fd
= -1;
820 gsc_handle
->op_mutex
= NULL
;
821 gsc_handle
->cur_obj_mutex
= NULL
;
822 gsc_handle
->destroy_cur_obj_mutex
= true;
824 sprintf(mutex_name
, "%sObject%d", LOG_TAG
, dev_num
);
825 gsc_handle
->cur_obj_mutex
= exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED
, mutex_name
);
826 if (gsc_handle
->cur_obj_mutex
== NULL
) {
827 ALOGE("%s::exynos_mutex_create(%s) fail", __func__
, mutex_name
);
832 if (exynos_mutex_trylock(gsc_handle
->cur_obj_mutex
) == true) {
836 usleep(GSC_WAITING_TIME_FOR_TRYLOCK
);
837 total_sleep_time
+= GSC_WAITING_TIME_FOR_TRYLOCK
;
838 ALOGV("%s::waiting for another process to release the requested gscaler", __func__
);
839 } while(total_sleep_time
< MAX_GSC_WAITING_TIME_FOR_TRYLOCK
);
841 if (gsc_flag
== true)
842 return (void *)gsc_handle
;
852 void exynos_gsc_release(void *handle
)
854 struct GSC_HANDLE
*gsc_handle
= (struct GSC_HANDLE
*)handle
;
856 if (handle
== NULL
) {
857 ALOGE("%s::handle == NULL() fail", __func__
);
861 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
862 exynos_mutex_destroy(gsc_handle
->cur_obj_mutex
);
867 void *exynos_gsc_create_exclusive(
876 unsigned int total_sleep_time
= 0;
877 bool gsc_flag
= false;
882 if ((dev_num
< 0) || (dev_num
>= NUM_OF_GSC_HW
)) {
883 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__
, dev_num
);
887 if ((mode
< 0) || (mode
>= NUM_OF_GSC_HW
)) {
888 ALOGE("%s::fail:: mode is not valid(%d) ", __func__
, mode
);
892 /* currently only gscalers 0 and 3 are DRM capable */
893 if (allow_drm
&& (dev_num
!= 0 && dev_num
!= 3)) {
894 ALOGE("%s::fail:: gscaler %d does not support drm\n", __func__
,
899 struct GSC_HANDLE
*gsc_handle
= (struct GSC_HANDLE
*)malloc(sizeof(struct GSC_HANDLE
));
900 if (gsc_handle
== NULL
) {
901 ALOGE("%s::malloc(struct GSC_HANDLE) fail", __func__
);
904 memset(gsc_handle
, 0, sizeof(struct GSC_HANDLE
));
905 gsc_handle
->gsc_fd
= -1;
906 gsc_handle
->gsc_mode
= mode
;
907 gsc_handle
->gsc_id
= dev_num
;
908 gsc_handle
->allow_drm
= allow_drm
;
910 gsc_handle
->src
.buf_type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
911 gsc_handle
->dst
.buf_type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
913 gsc_handle
->op_mutex
= NULL
;
914 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++)
915 gsc_handle
->obj_mutex
[i
] = NULL
;
917 gsc_handle
->cur_obj_mutex
= NULL
;
918 gsc_handle
->destroy_cur_obj_mutex
= false;
919 gsc_handle
->flag_local_path
= false;
920 gsc_handle
->flag_exclusive_open
= true;
923 op_id
= rand() % 1000000; // just make random id
924 sprintf(mutex_name
, "%sOp%d", LOG_TAG
, op_id
);
925 gsc_handle
->op_mutex
= exynos_mutex_create(EXYNOS_MUTEX_TYPE_PRIVATE
, mutex_name
);
926 if (gsc_handle
->op_mutex
== NULL
) {
927 ALOGE("%s::exynos_mutex_create(%s) fail", __func__
, mutex_name
);
931 exynos_mutex_lock(gsc_handle
->op_mutex
);
933 sprintf(mutex_name
, "%sObject%d", LOG_TAG
, dev_num
);
934 gsc_handle
->cur_obj_mutex
= exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED
, mutex_name
);
935 if (gsc_handle
->cur_obj_mutex
== NULL
) {
936 ALOGE("%s::exynos_mutex_create(%s) fail", __func__
, mutex_name
);
939 gsc_handle
->destroy_cur_obj_mutex
= true;
942 if (exynos_mutex_trylock(gsc_handle
->cur_obj_mutex
) == true) {
943 if (mode
== GSC_M2M_MODE
) {
944 gsc_handle
->gsc_fd
= m_exynos_gsc_m2m_create(dev_num
);
945 if (gsc_handle
->gsc_fd
< 0) {
946 ALOGE("%s::m_exynos_gsc_m2m_create(%i) fail", __func__
, dev_num
);
949 } else if (mode
== GSC_OUTPUT_MODE
) {
950 ret
= m_exynos_gsc_output_create(gsc_handle
, dev_num
, out_mode
);
952 ALOGE("%s::m_exynos_gsc_output_create(%i) fail", __func__
, dev_num
);
957 gsc_handle->gsc_fd = m_exynos_gsc_capture_create(dev_num);*/
962 usleep(GSC_WAITING_TIME_FOR_TRYLOCK
);
963 total_sleep_time
+= GSC_WAITING_TIME_FOR_TRYLOCK
;
964 ALOGV("%s::waiting for anthere process doens't use gscaler", __func__
);
965 } while(total_sleep_time
< MAX_GSC_WAITING_TIME_FOR_TRYLOCK
);
967 exynos_mutex_unlock(gsc_handle
->op_mutex
);
968 if (gsc_flag
== true) {
970 return (void *)gsc_handle
;
975 m_exynos_gsc_destroy(gsc_handle
);
977 if (gsc_handle
->cur_obj_mutex
) {
978 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
979 if (gsc_handle
->destroy_cur_obj_mutex
)
980 exynos_mutex_destroy(gsc_handle
->cur_obj_mutex
);
983 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++) {
984 if ((gsc_handle
->obj_mutex
[i
] != NULL
) &&
985 (exynos_mutex_get_created_status(gsc_handle
->obj_mutex
[i
]) == true)) {
986 if (exynos_mutex_destroy(gsc_handle
->obj_mutex
[i
]) == false)
987 ALOGE("%s::exynos_mutex_destroy() fail", __func__
);
991 if (gsc_handle
->op_mutex
)
992 exynos_mutex_unlock(gsc_handle
->op_mutex
);
994 if (exynos_mutex_destroy(gsc_handle
->op_mutex
) == false)
995 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__
);
1005 void exynos_gsc_destroy(
1009 struct GSC_HANDLE
*gsc_handle
= (struct GSC_HANDLE
*)handle
;
1013 if (handle
== NULL
) {
1014 ALOGE("%s::handle == NULL() fail", __func__
);
1018 exynos_mutex_lock(gsc_handle
->op_mutex
);
1020 if (gsc_handle
->flag_exclusive_open
== false)
1021 exynos_mutex_lock(gsc_handle
->cur_obj_mutex
);
1023 if (gsc_handle
->gsc_mode
== GSC_OUTPUT_MODE
)
1024 m_exynos_gsc_out_destroy(gsc_handle
);
1026 m_exynos_gsc_destroy(gsc_handle
);
1028 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
1030 for (i
= 0; i
< NUM_OF_GSC_HW
; i
++) {
1031 if ((gsc_handle
->obj_mutex
[i
] != NULL
) &&
1032 (exynos_mutex_get_created_status(gsc_handle
->obj_mutex
[i
]) == true)) {
1033 if (exynos_mutex_destroy(gsc_handle
->obj_mutex
[i
]) == false)
1034 ALOGE("%s::exynos_mutex_destroy(obj_mutex) fail", __func__
);
1038 if (gsc_handle
->destroy_cur_obj_mutex
)
1039 exynos_mutex_destroy(gsc_handle
->cur_obj_mutex
);
1041 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1043 if (exynos_mutex_destroy(gsc_handle
->op_mutex
) == false)
1044 ALOGE("%s::exynos_mutex_destroy(op_mutex) fail", __func__
);
1053 int exynos_gsc_set_src_format(
1056 unsigned int height
,
1057 unsigned int crop_left
,
1058 unsigned int crop_top
,
1059 unsigned int crop_width
,
1060 unsigned int crop_height
,
1061 unsigned int v4l2_colorformat
,
1062 unsigned int cacheable
,
1063 unsigned int mode_drm
)
1067 struct GSC_HANDLE
*gsc_handle
;
1068 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1070 if (handle
== NULL
) {
1071 ALOGE("%s::handle == NULL() fail", __func__
);
1075 exynos_mutex_lock(gsc_handle
->op_mutex
);
1077 gsc_handle
->src
.width
= width
;
1078 gsc_handle
->src
.height
= height
;
1079 gsc_handle
->src
.crop_left
= crop_left
;
1080 gsc_handle
->src
.crop_top
= crop_top
;
1081 gsc_handle
->src
.crop_width
= crop_width
;
1082 gsc_handle
->src
.crop_height
= crop_height
;
1083 gsc_handle
->src
.v4l2_colorformat
= v4l2_colorformat
;
1084 gsc_handle
->src
.cacheable
= cacheable
;
1085 gsc_handle
->src
.mode_drm
= mode_drm
;
1086 gsc_handle
->src
.dirty
= true;
1089 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1096 int exynos_gsc_set_dst_format(
1099 unsigned int height
,
1100 unsigned int crop_left
,
1101 unsigned int crop_top
,
1102 unsigned int crop_width
,
1103 unsigned int crop_height
,
1104 unsigned int v4l2_colorformat
,
1105 unsigned int cacheable
,
1106 unsigned int mode_drm
,
1107 unsigned int narrowRgb
)
1111 struct GSC_HANDLE
*gsc_handle
;
1112 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1114 if (handle
== NULL
) {
1115 ALOGE("%s::handle == NULL() fail", __func__
);
1119 exynos_mutex_lock(gsc_handle
->op_mutex
);
1121 gsc_handle
->dst
.width
= width
;
1122 gsc_handle
->dst
.height
= height
;
1123 gsc_handle
->dst
.crop_left
= crop_left
;
1124 gsc_handle
->dst
.crop_top
= crop_top
;
1125 gsc_handle
->dst
.crop_width
= crop_width
;
1126 gsc_handle
->dst
.crop_height
= crop_height
;
1127 gsc_handle
->dst
.v4l2_colorformat
= v4l2_colorformat
;
1128 gsc_handle
->dst
.cacheable
= cacheable
;
1129 gsc_handle
->dst
.mode_drm
= mode_drm
;
1130 gsc_handle
->dst
.dirty
= true;
1131 gsc_handle
->dst
.csc_range
= !narrowRgb
;
1133 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1139 int exynos_gsc_set_rotation(
1142 int flip_horizontal
,
1146 struct GSC_HANDLE
*gsc_handle
;
1147 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1149 if (handle
== NULL
) {
1150 ALOGE("%s::handle == NULL() fail", __func__
);
1154 exynos_mutex_lock(gsc_handle
->op_mutex
);
1156 int new_rotation
= rotation
% 360;
1158 if (new_rotation
% 90 != 0) {
1159 ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__
, rotation
);
1163 if(new_rotation
< 0)
1164 new_rotation
= -new_rotation
;
1166 gsc_handle
->dst
.rotation
= new_rotation
;
1167 gsc_handle
->dst
.flip_horizontal
= flip_horizontal
;
1168 gsc_handle
->dst
.flip_vertical
= flip_vertical
;
1172 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1177 int exynos_gsc_set_src_addr(
1182 struct GSC_HANDLE
*gsc_handle
;
1183 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1187 if (handle
== NULL
) {
1188 ALOGE("%s::handle == NULL() fail", __func__
);
1192 exynos_mutex_lock(gsc_handle
->op_mutex
);
1194 gsc_handle
->src
.addr
[0] = addr
[0];
1195 gsc_handle
->src
.addr
[1] = addr
[1];
1196 gsc_handle
->src
.addr
[2] = addr
[2];
1197 gsc_handle
->src
.acquireFenceFd
= acquireFenceFd
;
1199 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1206 int exynos_gsc_set_dst_addr(
1211 struct GSC_HANDLE
*gsc_handle
;
1212 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1217 if (handle
== NULL
) {
1218 ALOGE("%s::handle == NULL() fail", __func__
);
1222 exynos_mutex_lock(gsc_handle
->op_mutex
);
1224 gsc_handle
->dst
.addr
[0] = addr
[0];
1225 gsc_handle
->dst
.addr
[1] = addr
[1];
1226 gsc_handle
->dst
.addr
[2] = addr
[2];
1227 gsc_handle
->dst
.acquireFenceFd
= acquireFenceFd
;
1230 exynos_mutex_unlock(gsc_handle
->op_mutex
);
1237 static void rotateValueHAL2GSC(unsigned int transform
,
1238 unsigned int *rotate
,
1239 unsigned int *hflip
,
1240 unsigned int *vflip
)
1242 int rotate_flag
= transform
& 0x7;
1247 switch (rotate_flag
) {
1248 case HAL_TRANSFORM_ROT_90
:
1251 case HAL_TRANSFORM_ROT_180
:
1254 case HAL_TRANSFORM_ROT_270
:
1257 case HAL_TRANSFORM_FLIP_H
| HAL_TRANSFORM_ROT_90
:
1259 *vflip
= 1; /* set vflip to compensate the rot & flip order. */
1261 case HAL_TRANSFORM_FLIP_V
| HAL_TRANSFORM_ROT_90
:
1263 *hflip
= 1; /* set hflip to compensate the rot & flip order. */
1265 case HAL_TRANSFORM_FLIP_H
:
1268 case HAL_TRANSFORM_FLIP_V
:
1276 static bool get_plane_size(int V4L2_PIX
,
1277 unsigned int * size
,
1278 unsigned int frame_size
,
1281 unsigned int frame_ratio
= 1;
1282 int src_bpp
= get_yuv_bpp(V4L2_PIX
);
1284 src_planes
= (src_planes
== -1) ? 1 : src_planes
;
1285 frame_ratio
= 8 * (src_planes
-1) / (src_bpp
- 8);
1287 switch (src_planes
) {
1290 case V4L2_PIX_FMT_BGR32
:
1291 case V4L2_PIX_FMT_RGB32
:
1292 size
[0] = frame_size
<< 2;
1294 case V4L2_PIX_FMT_RGB565X
:
1295 case V4L2_PIX_FMT_NV16
:
1296 case V4L2_PIX_FMT_NV61
:
1297 case V4L2_PIX_FMT_YUYV
:
1298 case V4L2_PIX_FMT_UYVY
:
1299 case V4L2_PIX_FMT_VYUY
:
1300 case V4L2_PIX_FMT_YVYU
:
1301 size
[0] = frame_size
<< 1;
1303 case V4L2_PIX_FMT_YUV420
:
1304 case V4L2_PIX_FMT_NV12
:
1305 case V4L2_PIX_FMT_NV21
:
1306 case V4L2_PIX_FMT_NV21M
:
1307 size
[0] = (frame_size
* 3) >> 1;
1310 ALOGE("%s::invalid color type", __func__
);
1318 size
[0] = frame_size
;
1319 size
[1] = frame_size
/ frame_ratio
;
1323 size
[0] = frame_size
;
1324 size
[1] = frame_size
/ frame_ratio
;
1325 size
[2] = frame_size
/ frame_ratio
;
1328 ALOGE("%s::invalid color foarmt", __func__
);
1336 int exynos_gsc_m2m_config(void *handle
,
1337 exynos_gsc_img
*src_img
,
1338 exynos_gsc_img
*dst_img
)
1340 struct GSC_HANDLE
*gsc_handle
;
1341 int32_t src_color_space
;
1342 int32_t dst_color_space
;
1344 unsigned int rotate
;
1350 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1351 if (gsc_handle
== NULL
) {
1352 ALOGE("%s::gsc_handle == NULL() fail", __func__
);
1356 if ((src_img
->drmMode
&& !gsc_handle
->allow_drm
) ||
1357 (src_img
->drmMode
!= dst_img
->drmMode
)) {
1358 ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
1359 __func__
, gsc_handle
->gsc_id
,
1360 src_img
->drmMode
, dst_img
->drmMode
);
1364 src_color_space
= HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img
->format
);
1365 dst_color_space
= HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img
->format
);
1366 rotateValueHAL2GSC(dst_img
->rot
, &rotate
, &hflip
, &vflip
);
1367 exynos_gsc_set_rotation(gsc_handle
, rotate
, hflip
, vflip
);
1369 ret
= exynos_gsc_set_src_format(gsc_handle
, src_img
->fw
, src_img
->fh
,
1370 src_img
->x
, src_img
->y
, src_img
->w
, src_img
->h
,
1371 src_color_space
, src_img
->cacheable
, src_img
->drmMode
);
1373 ALOGE("%s: fail: exynos_gsc_set_src_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1374 __func__
, src_img
->fw
, src_img
->fh
, src_img
->x
, src_img
->y
, src_img
->w
, src_img
->h
,
1375 src_color_space
, src_img
->rot
);
1379 ret
= exynos_gsc_set_dst_format(gsc_handle
, dst_img
->fw
, dst_img
->fh
,
1380 dst_img
->x
, dst_img
->y
, dst_img
->w
, dst_img
->h
,
1381 dst_color_space
, dst_img
->cacheable
, dst_img
->drmMode
,
1382 dst_img
->narrowRgb
);
1384 ALOGE("%s: fail: exynos_gsc_set_dst_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1385 __func__
, dst_img
->fw
, dst_img
->fh
, dst_img
->x
, dst_img
->y
, dst_img
->w
, dst_img
->h
,
1386 src_color_space
, dst_img
->rot
);
1395 int exynos_gsc_out_config(void *handle
,
1396 exynos_gsc_img
*src_img
,
1397 exynos_gsc_img
*dst_img
)
1399 struct GSC_HANDLE
*gsc_handle
;
1400 struct v4l2_format fmt
;
1401 struct v4l2_crop crop
;
1402 struct v4l2_requestbuffers reqbuf
;
1403 struct v4l2_subdev_format sd_fmt
;
1404 struct v4l2_subdev_crop sd_crop
;
1406 unsigned int rotate
;
1409 unsigned int plane_size
[NUM_OF_GSC_PLANES
];
1411 int csc_range
= !dst_img
->narrowRgb
;
1413 struct v4l2_rect dst_rect
;
1414 int32_t src_color_space
;
1415 int32_t dst_color_space
;
1418 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1419 if (gsc_handle
== NULL
) {
1420 ALOGE("%s::gsc_handle == NULL() fail", __func__
);
1426 if (gsc_handle
->src
.stream_on
!= false) {
1427 ALOGE("Error: Src is already streamed on !!!!");
1431 memcpy(&gsc_handle
->src_img
, src_img
, sizeof(exynos_gsc_img
));
1432 memcpy(&gsc_handle
->dst_img
, dst_img
, sizeof(exynos_gsc_img
));
1433 src_color_space
= HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img
->format
);
1434 dst_color_space
= HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img
->format
);
1435 src_planes
= get_yuv_planes(src_color_space
);
1436 src_planes
= (src_planes
== -1) ? 1 : src_planes
;
1437 rgb
= get_yuv_planes(dst_color_space
) == -1;
1438 rotateValueHAL2GSC(dst_img
->rot
, &rotate
, &hflip
, &vflip
);
1440 if (m_exynos_gsc_check_src_size(&gsc_handle
->src_img
.fw
, &gsc_handle
->src_img
.fh
,
1441 &gsc_handle
->src_img
.x
, &gsc_handle
->src_img
.y
,
1442 &gsc_handle
->src_img
.w
, &gsc_handle
->src_img
.h
,
1443 src_color_space
) == false) {
1444 ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__
);
1448 if (m_exynos_gsc_check_dst_size(&gsc_handle
->dst_img
.fw
, &gsc_handle
->dst_img
.fh
,
1449 &gsc_handle
->dst_img
.x
, &gsc_handle
->dst_img
.y
,
1450 &gsc_handle
->dst_img
.w
, &gsc_handle
->dst_img
.h
,
1453 ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__
);
1457 /*set: src v4l2_buffer*/
1458 gsc_handle
->src
.src_buf_idx
= 0;
1459 gsc_handle
->src
.qbuf_cnt
= 0;
1460 /* set format: src pad of GSC sub-dev*/
1461 sd_fmt
.pad
= GSCALER_SUBDEV_PAD_SOURCE
;
1462 sd_fmt
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1463 if (gsc_handle
->out_mode
== GSC_OUT_FIMD
) {
1464 sd_fmt
.format
.width
= gsc_handle
->dst_img
.fw
;
1465 sd_fmt
.format
.height
= gsc_handle
->dst_img
.fh
;
1467 sd_fmt
.format
.width
= gsc_handle
->dst_img
.w
;
1468 sd_fmt
.format
.height
= gsc_handle
->dst_img
.h
;
1470 sd_fmt
.format
.code
= rgb
? V4L2_MBUS_FMT_XRGB8888_4X8_LE
:
1471 V4L2_MBUS_FMT_YUV8_1X24
;
1472 if (exynos_subdev_s_fmt(gsc_handle
->gsc_sd_entity
->fd
, &sd_fmt
) < 0) {
1473 ALOGE("%s::GSC subdev set format failed", __func__
);
1477 /* set crop: src crop of GSC sub-dev*/
1478 sd_crop
.pad
= GSCALER_SUBDEV_PAD_SOURCE
;
1479 sd_crop
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1480 if (gsc_handle
->out_mode
== GSC_OUT_FIMD
) {
1481 sd_crop
.rect
.left
= gsc_handle
->dst_img
.x
;
1482 sd_crop
.rect
.top
= gsc_handle
->dst_img
.y
;
1483 sd_crop
.rect
.width
= gsc_handle
->dst_img
.w
;
1484 sd_crop
.rect
.height
= gsc_handle
->dst_img
.h
;
1486 sd_crop
.rect
.left
= 0;
1487 sd_crop
.rect
.top
= 0;
1488 sd_crop
.rect
.width
= gsc_handle
->dst_img
.w
;
1489 sd_crop
.rect
.height
= gsc_handle
->dst_img
.h
;
1491 if (exynos_subdev_s_crop(gsc_handle
->gsc_sd_entity
->fd
, &sd_crop
) < 0) {
1492 ALOGE("%s::GSC subdev set crop failed", __func__
);
1496 /* sink pad is connected to GSC out */
1497 /* set format: sink sub-dev */
1498 if (gsc_handle
->out_mode
== GSC_OUT_FIMD
) {
1499 sd_fmt
.pad
= FIMD_SUBDEV_PAD_SINK
;
1500 sd_fmt
.format
.width
= gsc_handle
->dst_img
.w
;
1501 sd_fmt
.format
.height
= gsc_handle
->dst_img
.h
;
1503 sd_fmt
.pad
= MIXER_V_SUBDEV_PAD_SINK
;
1504 sd_fmt
.format
.width
= gsc_handle
->dst_img
.w
+ gsc_handle
->dst_img
.x
*2;
1505 sd_fmt
.format
.height
= gsc_handle
->dst_img
.h
+ gsc_handle
->dst_img
.y
*2;
1508 sd_fmt
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1509 sd_fmt
.format
.code
= rgb
? V4L2_MBUS_FMT_XRGB8888_4X8_LE
:
1510 V4L2_MBUS_FMT_YUV8_1X24
;
1511 if (exynos_subdev_s_fmt(gsc_handle
->sink_sd_entity
->fd
, &sd_fmt
) < 0) {
1512 ALOGE("%s::sink:set format failed (PAD=%d)", __func__
, sd_fmt
.pad
);
1516 /* set crop: sink sub-dev */
1517 if (gsc_handle
->out_mode
== GSC_OUT_FIMD
)
1518 sd_crop
.pad
= FIMD_SUBDEV_PAD_SINK
;
1520 sd_crop
.pad
= MIXER_V_SUBDEV_PAD_SINK
;
1522 sd_crop
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1523 if (gsc_handle
->out_mode
== GSC_OUT_FIMD
) {
1524 sd_crop
.rect
.left
= gsc_handle
->dst_img
.x
;
1525 sd_crop
.rect
.top
= gsc_handle
->dst_img
.y
;
1526 sd_crop
.rect
.width
= gsc_handle
->dst_img
.w
;
1527 sd_crop
.rect
.height
= gsc_handle
->dst_img
.h
;
1529 sd_crop
.rect
.left
= 0;
1530 sd_crop
.rect
.top
= 0;
1531 sd_crop
.rect
.width
= gsc_handle
->dst_img
.w
;
1532 sd_crop
.rect
.height
= gsc_handle
->dst_img
.h
;
1534 if (exynos_subdev_s_crop(gsc_handle
->sink_sd_entity
->fd
, &sd_crop
) < 0) {
1535 ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__
, sd_crop
.pad
);
1539 if (gsc_handle
->out_mode
!= GSC_OUT_FIMD
) {
1540 sd_fmt
.pad
= MIXER_V_SUBDEV_PAD_SOURCE
;
1541 sd_fmt
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1542 sd_fmt
.format
.width
= gsc_handle
->dst_img
.w
+ gsc_handle
->dst_img
.x
*2;
1543 sd_fmt
.format
.height
= gsc_handle
->dst_img
.h
+ gsc_handle
->dst_img
.y
*2;
1544 sd_fmt
.format
.code
= V4L2_MBUS_FMT_XRGB8888_4X8_LE
;
1545 if (exynos_subdev_s_fmt(gsc_handle
->sink_sd_entity
->fd
, &sd_fmt
) < 0) {
1546 ALOGE("%s::sink:set format failed (PAD=%d)", __func__
, sd_fmt
.pad
);
1550 sd_fmt
.pad
= MIXER_V_SUBDEV_PAD_SOURCE
;
1551 sd_crop
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
1552 sd_crop
.rect
.left
= gsc_handle
->dst_img
.x
;
1553 sd_crop
.rect
.top
= gsc_handle
->dst_img
.y
;
1554 sd_crop
.rect
.width
= gsc_handle
->dst_img
.w
;
1555 sd_crop
.rect
.height
= gsc_handle
->dst_img
.h
;
1556 if (exynos_subdev_s_crop(gsc_handle
->sink_sd_entity
->fd
, &sd_crop
) < 0) {
1557 ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__
, sd_crop
.pad
);
1563 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
, V4L2_CID_ROTATE
, rotate
) < 0) {
1564 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed", __func__
, rotate
);
1568 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
, V4L2_CID_HFLIP
, hflip
) < 0) {
1569 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed", __func__
, hflip
);
1573 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
, V4L2_CID_VFLIP
, vflip
) < 0) {
1574 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed", __func__
, vflip
);
1578 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
, V4L2_CID_CACHEABLE
, 1) < 0) {
1579 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed", __func__
);
1583 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
,
1584 V4L2_CID_CONTENT_PROTECTION
, gsc_handle
->src_img
.drmMode
) < 0) {
1585 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail", __func__
);
1589 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_vd_entity
->fd
, V4L2_CID_CSC_RANGE
,
1591 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail", __func__
,
1596 /* set src format :GSC video dev*/
1597 fmt
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1598 fmt
.fmt
.pix_mp
.width
= gsc_handle
->src_img
.fw
;
1599 fmt
.fmt
.pix_mp
.height
= gsc_handle
->src_img
.fh
;
1600 fmt
.fmt
.pix_mp
.pixelformat
= src_color_space
;
1601 fmt
.fmt
.pix_mp
.field
= V4L2_FIELD_NONE
;
1602 fmt
.fmt
.pix_mp
.num_planes
= src_planes
;
1604 if (exynos_v4l2_s_fmt(gsc_handle
->gsc_vd_entity
->fd
, &fmt
) < 0) {
1605 ALOGE("%s::videodev set format failed", __func__
);
1609 /* set src crop info :GSC video dev*/
1610 crop
.type
= fmt
.type
;
1611 crop
.c
.left
= gsc_handle
->src_img
.x
;
1612 crop
.c
.top
= gsc_handle
->src_img
.y
;
1613 crop
.c
.width
= gsc_handle
->src_img
.w
;
1614 crop
.c
.height
= gsc_handle
->src_img
.h
;
1616 if (exynos_v4l2_s_crop(gsc_handle
->gsc_vd_entity
->fd
, &crop
) < 0) {
1617 ALOGE("%s::videodev set crop failed", __func__
);
1621 reqbuf
.type
= fmt
.type
;
1622 reqbuf
.memory
= V4L2_MEMORY_DMABUF
;
1623 reqbuf
.count
= MAX_BUFFERS_GSCALER_OUT
;
1625 if (exynos_v4l2_reqbufs(gsc_handle
->gsc_vd_entity
->fd
, &reqbuf
) < 0) {
1626 ALOGE("%s::request buffers failed", __func__
);
1635 static int exynos_gsc_out_run(void *handle
,
1636 exynos_gsc_img
*src_img
)
1638 struct GSC_HANDLE
*gsc_handle
;
1639 struct v4l2_plane planes
[NUM_OF_GSC_PLANES
];
1640 struct v4l2_buffer buf
;
1641 int32_t src_color_space
;
1644 unsigned int plane_size
[NUM_OF_GSC_PLANES
];
1646 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1647 if (handle
== NULL
) {
1648 ALOGE("%s::handle == NULL() fail", __func__
);
1652 /* All buffers have been queued, dequeue one */
1653 if (gsc_handle
->src
.qbuf_cnt
== MAX_BUFFERS_GSCALER_OUT
) {
1654 memset(&buf
, 0, sizeof(struct v4l2_buffer
));
1655 for (i
= 0; i
< MAX_BUFFERS_GSCALER_OUT
; i
++)
1656 memset(&planes
[i
], 0, sizeof(struct v4l2_plane
));
1658 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1659 buf
.memory
= V4L2_MEMORY_DMABUF
;
1660 buf
.length
= src_planes
;
1661 buf
.m
.planes
= planes
;
1663 if (exynos_v4l2_dqbuf(gsc_handle
->gsc_vd_entity
->fd
, &buf
) < 0) {
1664 ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)", __func__
,
1665 gsc_handle
->src
.src_buf_idx
, MAX_BUFFERS_GSCALER_OUT
);
1668 gsc_handle
->src
.qbuf_cnt
--;
1671 memset(&buf
, 0, sizeof(struct v4l2_buffer
));
1672 for (i
= 0; i
< NUM_OF_GSC_PLANES
; i
++)
1673 memset(&planes
[i
], 0, sizeof(struct v4l2_plane
));
1675 src_color_space
= HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc_handle
->src_img
.format
);
1676 src_planes
= get_yuv_planes(src_color_space
);
1677 src_planes
= (src_planes
== -1) ? 1 : src_planes
;
1679 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1680 buf
.memory
= V4L2_MEMORY_DMABUF
;
1681 buf
.flags
= V4L2_BUF_FLAG_USE_SYNC
;
1682 buf
.length
= src_planes
;
1683 buf
.index
= gsc_handle
->src
.src_buf_idx
;
1684 buf
.m
.planes
= planes
;
1685 buf
.reserved
= src_img
->acquireFenceFd
;
1687 gsc_handle
->src
.addr
[0] = src_img
->yaddr
;
1688 gsc_handle
->src
.addr
[1] = src_img
->uaddr
;
1689 gsc_handle
->src
.addr
[2] = src_img
->vaddr
;
1691 if (get_plane_size(src_color_space
, plane_size
,
1692 gsc_handle
->src_img
.fw
* gsc_handle
->src_img
.fh
, src_planes
) != true) {
1693 ALOGE("%s:get_plane_size:fail", __func__
);
1697 for (i
= 0; i
< buf
.length
; i
++) {
1698 buf
.m
.planes
[i
].m
.fd
= (int)gsc_handle
->src
.addr
[i
];
1699 buf
.m
.planes
[i
].length
= plane_size
[i
];
1700 buf
.m
.planes
[i
].bytesused
= plane_size
[i
];
1704 if (exynos_v4l2_qbuf(gsc_handle
->gsc_vd_entity
->fd
, &buf
) < 0) {
1705 ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)", __func__
,
1706 gsc_handle
->src
.src_buf_idx
, MAX_BUFFERS_GSCALER_OUT
);
1709 gsc_handle
->src
.src_buf_idx
++;
1710 gsc_handle
->src
.src_buf_idx
= gsc_handle
->src
.src_buf_idx
% MAX_BUFFERS_GSCALER_OUT
;
1711 gsc_handle
->src
.qbuf_cnt
++;
1713 if (gsc_handle
->src
.stream_on
== false) {
1714 if (exynos_v4l2_streamon(gsc_handle
->gsc_vd_entity
->fd
, buf
.type
) < 0) {
1715 ALOGE("%s::stream on failed", __func__
);
1718 gsc_handle
->src
.stream_on
= true;
1721 src_img
->releaseFenceFd
= buf
.reserved
;
1725 int exynos_gsc_out_stop(void *handle
)
1727 struct GSC_HANDLE
*gsc_handle
;
1728 struct v4l2_requestbuffers reqbuf
;
1729 struct v4l2_buffer buf
;
1730 struct v4l2_plane planes
[NUM_OF_GSC_PLANES
];
1735 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1736 if (handle
== NULL
) {
1737 ALOGE("%s::handle == NULL() fail", __func__
);
1741 if (gsc_handle
->src
.stream_on
== true) {
1742 if (exynos_v4l2_streamoff(gsc_handle
->gsc_vd_entity
->fd
,
1743 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) < 0) {
1744 ALOGE("%s::stream off failed", __func__
);
1747 gsc_handle
->src
.stream_on
= false;
1750 gsc_handle
->src
.src_buf_idx
= 0;
1751 gsc_handle
->src
.qbuf_cnt
= 0;
1753 reqbuf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1754 reqbuf
.memory
= V4L2_MEMORY_DMABUF
;
1757 if (exynos_v4l2_reqbufs(gsc_handle
->gsc_vd_entity
->fd
, &reqbuf
) < 0) {
1758 ALOGE("%s::request buffers failed", __func__
);
1767 static int exynos_gsc_m2m_run_core(void *handle
)
1769 struct GSC_HANDLE
*gsc_handle
;
1773 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1777 if (handle
== NULL
) {
1778 ALOGE("%s::handle == NULL() fail", __func__
);
1782 is_dirty
= gsc_handle
->src
.dirty
|| gsc_handle
->dst
.dirty
;
1783 is_drm
= gsc_handle
->src
.mode_drm
;
1785 if (is_dirty
&& (gsc_handle
->src
.mode_drm
!= gsc_handle
->dst
.mode_drm
)) {
1786 ALOGE("%s: drm mode mismatch between src and dst, gsc%d (s=%d d=%d)",
1787 __func__
, gsc_handle
->gsc_id
, gsc_handle
->src
.mode_drm
,
1788 gsc_handle
->dst
.mode_drm
);
1790 } else if (is_drm
&& !gsc_handle
->allow_drm
) {
1791 ALOGE("%s: drm mode is not supported on gsc%d", __func__
,
1792 gsc_handle
->gsc_id
);
1796 if (m_exynos_gsc_check_src_size(&gsc_handle
->src
.width
, &gsc_handle
->src
.height
,
1797 &gsc_handle
->src
.crop_left
, &gsc_handle
->src
.crop_top
,
1798 &gsc_handle
->src
.crop_width
, &gsc_handle
->src
.crop_height
,
1799 gsc_handle
->src
.v4l2_colorformat
) == false) {
1800 ALOGE("%s::m_exynos_gsc_check_src_size() fail", __func__
);
1804 if (m_exynos_gsc_check_dst_size(&gsc_handle
->dst
.width
, &gsc_handle
->dst
.height
,
1805 &gsc_handle
->dst
.crop_left
, &gsc_handle
->dst
.crop_top
,
1806 &gsc_handle
->dst
.crop_width
, &gsc_handle
->dst
.crop_height
,
1807 gsc_handle
->dst
.v4l2_colorformat
,
1808 gsc_handle
->dst
.rotation
) == false) {
1809 ALOGE("%s::m_exynos_gsc_check_dst_size() fail", __func__
);
1813 /* dequeue buffers from previous work if necessary */
1814 if (gsc_handle
->src
.stream_on
== true) {
1815 if (exynos_gsc_m2m_wait_frame_done(handle
) < 0) {
1816 ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__
);
1822 * need to set the content protection flag before doing reqbufs
1825 if (is_dirty
&& gsc_handle
->allow_drm
&& is_drm
) {
1826 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_fd
,
1827 V4L2_CID_CONTENT_PROTECTION
, is_drm
) < 0) {
1828 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__
);
1834 * from this point on, we have to ensure to call stop to clean up whatever
1835 * state we have set.
1838 if (gsc_handle
->src
.dirty
) {
1839 if (m_exynos_gsc_set_format(gsc_handle
->gsc_fd
, &gsc_handle
->src
) == false) {
1840 ALOGE("%s::m_exynos_gsc_set_format(src) fail", __func__
);
1843 gsc_handle
->src
.dirty
= false;
1846 if (gsc_handle
->dst
.dirty
) {
1847 if (m_exynos_gsc_set_format(gsc_handle
->gsc_fd
, &gsc_handle
->dst
) == false) {
1848 ALOGE("%s::m_exynos_gsc_set_format(dst) fail", __func__
);
1851 gsc_handle
->dst
.dirty
= false;
1854 /* if we are enabling drm, make sure to enable hw protection.
1855 * Need to do this before queuing buffers so that the mmu is reserved
1856 * and power domain is kept on.
1858 if (is_dirty
&& gsc_handle
->allow_drm
&& is_drm
) {
1859 unsigned int protect_id
= 0;
1861 if (gsc_handle
->gsc_id
== 0) {
1862 protect_id
= CP_PROTECT_GSC0
;
1863 } else if (gsc_handle
->gsc_id
== 3) {
1864 protect_id
= CP_PROTECT_GSC3
;
1866 ALOGE("%s::invalid gscaler id %d for content protection", __func__
,
1867 gsc_handle
->gsc_id
);
1871 if (CP_Enable_Path_Protection(protect_id
) != 0) {
1872 ALOGE("%s::CP_Enable_Path_Protection failed", __func__
);
1875 gsc_handle
->protection_enabled
= true;
1878 if (m_exynos_gsc_set_addr(gsc_handle
->gsc_fd
, &gsc_handle
->src
) == false) {
1879 ALOGE("%s::m_exynos_gsc_set_addr(src) fail", __func__
);
1883 if (m_exynos_gsc_set_addr(gsc_handle
->gsc_fd
, &gsc_handle
->dst
) == false) {
1884 ALOGE("%s::m_exynos_gsc_set_addr(dst) fail", __func__
);
1888 if (gsc_handle
->src
.stream_on
== false) {
1889 if (exynos_v4l2_streamon(gsc_handle
->gsc_fd
, gsc_handle
->src
.buf_type
) < 0) {
1890 ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__
);
1893 gsc_handle
->src
.stream_on
= true;
1896 if (gsc_handle
->dst
.stream_on
== false) {
1897 if (exynos_v4l2_streamon(gsc_handle
->gsc_fd
, gsc_handle
->dst
.buf_type
) < 0) {
1898 ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__
);
1901 gsc_handle
->dst
.stream_on
= true;
1909 exynos_gsc_m2m_stop(handle
);
1913 static int exynos_gsc_m2m_wait_frame_done(void *handle
)
1915 struct GSC_HANDLE
*gsc_handle
;
1917 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1921 if (handle
== NULL
) {
1922 ALOGE("%s::handle == NULL() fail", __func__
);
1926 if ((gsc_handle
->src
.stream_on
== false) || (gsc_handle
->dst
.stream_on
== false)) {
1927 ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__
);
1931 if (gsc_handle
->src
.buffer_queued
) {
1932 if (exynos_v4l2_dqbuf(gsc_handle
->gsc_fd
, &gsc_handle
->src
.buffer
) < 0) {
1933 ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__
);
1936 gsc_handle
->src
.buffer_queued
= false;
1939 if (gsc_handle
->dst
.buffer_queued
) {
1940 if (exynos_v4l2_dqbuf(gsc_handle
->gsc_fd
, &gsc_handle
->dst
.buffer
) < 0) {
1941 ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__
);
1944 gsc_handle
->dst
.buffer_queued
= false;
1952 static int exynos_gsc_m2m_stop(void *handle
)
1954 struct GSC_HANDLE
*gsc_handle
;
1955 struct v4l2_requestbuffers req_buf
;
1958 gsc_handle
= (struct GSC_HANDLE
*)handle
;
1962 if (!gsc_handle
->src
.stream_on
&& !gsc_handle
->dst
.stream_on
) {
1963 /* wasn't streaming, return success */
1965 } else if (gsc_handle
->src
.stream_on
!= gsc_handle
->dst
.stream_on
) {
1966 ALOGE("%s: invalid state, queue stream state doesn't match (%d != %d)",
1967 __func__
, gsc_handle
->src
.stream_on
, gsc_handle
->dst
.stream_on
);
1972 * we need to plow forward on errors below to make sure that if we had
1973 * turned on content protection on secure side, we turn it off.
1975 * also, if we only failed to turn on one of the streams, we'll turn
1976 * the other one off correctly.
1978 if (gsc_handle
->src
.stream_on
== true) {
1979 if (exynos_v4l2_streamoff(gsc_handle
->gsc_fd
, gsc_handle
->src
.buf_type
) < 0) {
1980 ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__
);
1983 gsc_handle
->src
.stream_on
= false;
1987 if (gsc_handle
->dst
.stream_on
== true) {
1988 if (exynos_v4l2_streamoff(gsc_handle
->gsc_fd
, gsc_handle
->dst
.buf_type
) < 0) {
1989 ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__
);
1992 gsc_handle
->dst
.stream_on
= false;
1995 /* if drm is enabled */
1996 if (gsc_handle
->allow_drm
&& gsc_handle
->protection_enabled
) {
1997 unsigned int protect_id
= 0;
1999 if (gsc_handle
->gsc_id
== 0)
2000 protect_id
= CP_PROTECT_GSC0
;
2001 else if (gsc_handle
->gsc_id
== 3)
2002 protect_id
= CP_PROTECT_GSC3
;
2004 CP_Disable_Path_Protection(protect_id
);
2005 gsc_handle
->protection_enabled
= false;
2008 if (exynos_v4l2_s_ctrl(gsc_handle
->gsc_fd
,
2009 V4L2_CID_CONTENT_PROTECTION
, 0) < 0) {
2010 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
2015 /* src: clear_buf */
2017 req_buf
.type
= gsc_handle
->src
.buf_type
;
2018 req_buf
.memory
= V4L2_MEMORY_DMABUF
;
2019 if (exynos_v4l2_reqbufs(gsc_handle
->gsc_fd
, &req_buf
) < 0) {
2020 ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__
);
2024 /* dst: clear_buf */
2026 req_buf
.type
= gsc_handle
->dst
.buf_type
;
2027 req_buf
.memory
= V4L2_MEMORY_DMABUF
;
2028 if (exynos_v4l2_reqbufs(gsc_handle
->gsc_fd
, &req_buf
) < 0) {
2029 ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__
);
2038 int exynos_gsc_convert(
2041 struct GSC_HANDLE
*gsc_handle
;
2043 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2047 if (handle
== NULL
) {
2048 ALOGE("%s::handle == NULL() fail", __func__
);
2052 exynos_mutex_lock(gsc_handle
->op_mutex
);
2054 if (gsc_handle
->flag_local_path
== true) {
2055 ALOGE("%s::this exynos_gsc is connected by another hw internaly. So, don't call exynos_gsc_convert()", __func__
);
2059 if (exynos_gsc_m2m_run_core(handle
) < 0) {
2060 ALOGE("%s::exynos_gsc_run_core fail", __func__
);
2064 if (exynos_gsc_m2m_wait_frame_done(handle
) < 0) {
2065 ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__
);
2069 if (gsc_handle
->src
.releaseFenceFd
>= 0) {
2070 close(gsc_handle
->src
.releaseFenceFd
);
2071 gsc_handle
->src
.releaseFenceFd
= -1;
2074 if (gsc_handle
->dst
.releaseFenceFd
>= 0) {
2075 close(gsc_handle
->dst
.releaseFenceFd
);
2076 gsc_handle
->dst
.releaseFenceFd
= -1;
2079 if (exynos_gsc_m2m_stop(handle
) < 0) {
2080 ALOGE("%s::exynos_gsc_m2m_stop", __func__
);
2087 if (gsc_handle
->flag_exclusive_open
== false) {
2088 if (gsc_handle
->flag_local_path
== false)
2089 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
2092 exynos_mutex_unlock(gsc_handle
->op_mutex
);
2099 int exynos_gsc_m2m_run(void *handle
,
2100 exynos_gsc_img
*src_img
,
2101 exynos_gsc_img
*dst_img
)
2103 struct GSC_HANDLE
*gsc_handle
= handle
;
2104 void *addr
[3] = {NULL
, NULL
, NULL
};
2109 addr
[0] = (void *)src_img
->yaddr
;
2110 addr
[1] = (void *)src_img
->uaddr
;
2111 addr
[2] = (void *)src_img
->vaddr
;
2112 ret
= exynos_gsc_set_src_addr(handle
, addr
, src_img
->acquireFenceFd
);
2114 ALOGE("%s::fail: exynos_gsc_set_src_addr[%x %x %x]", __func__
,
2115 (unsigned int)addr
[0], (unsigned int)addr
[1], (unsigned int)addr
[2]);
2119 addr
[0] = (void *)dst_img
->yaddr
;
2120 addr
[1] = (void *)dst_img
->uaddr
;
2121 addr
[2] = (void *)dst_img
->vaddr
;
2122 ret
= exynos_gsc_set_dst_addr(handle
, addr
, dst_img
->acquireFenceFd
);
2124 ALOGE("%s::fail: exynos_gsc_set_dst_addr[%x %x %x]", __func__
,
2125 (unsigned int)addr
[0], (unsigned int)addr
[1], (unsigned int)addr
[2]);
2129 ret
= exynos_gsc_m2m_run_core(handle
);
2131 ALOGE("%s::fail: exynos_gsc_m2m_run_core", __func__
);
2135 if (src_img
->acquireFenceFd
>= 0) {
2136 close(src_img
->acquireFenceFd
);
2137 src_img
->acquireFenceFd
= -1;
2140 if (dst_img
->acquireFenceFd
>= 0) {
2141 close(dst_img
->acquireFenceFd
);
2142 dst_img
->acquireFenceFd
= -1;
2145 src_img
->releaseFenceFd
= gsc_handle
->src
.releaseFenceFd
;
2146 dst_img
->releaseFenceFd
= gsc_handle
->dst
.releaseFenceFd
;
2153 int exynos_gsc_config_exclusive(void *handle
,
2154 exynos_gsc_img
*src_img
,
2155 exynos_gsc_img
*dst_img
)
2160 struct GSC_HANDLE
*gsc_handle
;
2162 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2163 if (handle
== NULL
) {
2164 ALOGE("%s::handle == NULL() fail", __func__
);
2168 switch (gsc_handle
->gsc_mode
) {
2170 ret
= exynos_gsc_m2m_config(handle
, src_img
, dst_img
);
2172 case GSC_OUTPUT_MODE
:
2173 ret
= exynos_gsc_out_config(handle
, src_img
, dst_img
);
2175 case GSC_CAPTURE_MODE
:
2188 int exynos_gsc_run_exclusive(void *handle
,
2189 exynos_gsc_img
*src_img
,
2190 exynos_gsc_img
*dst_img
)
2192 struct GSC_HANDLE
*gsc_handle
;
2197 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2198 if (handle
== NULL
) {
2199 ALOGE("%s::handle == NULL() fail", __func__
);
2203 switch (gsc_handle
->gsc_mode
) {
2205 ret
= exynos_gsc_m2m_run(handle
, src_img
, dst_img
);
2207 case GSC_OUTPUT_MODE
:
2208 ret
= exynos_gsc_out_run(handle
, src_img
);
2210 case GSC_CAPTURE_MODE
:
2222 int exynos_gsc_wait_frame_done_exclusive(void *handle
)
2224 struct GSC_HANDLE
*gsc_handle
;
2226 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2230 if (handle
== NULL
) {
2231 ALOGE("%s::handle == NULL() fail", __func__
);
2235 if (gsc_handle
->gsc_mode
== GSC_M2M_MODE
)
2236 ret
= exynos_gsc_m2m_wait_frame_done(handle
);
2243 int exynos_gsc_stop_exclusive(void *handle
)
2245 struct GSC_HANDLE
*gsc_handle
;
2247 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2251 if (handle
== NULL
) {
2252 ALOGE("%s::handle == NULL() fail", __func__
);
2256 switch (gsc_handle
->gsc_mode
) {
2258 ret
= exynos_gsc_m2m_stop(handle
);
2260 case GSC_OUTPUT_MODE
:
2261 ret
= exynos_gsc_out_stop(handle
);
2263 case GSC_CAPTURE_MODE
:
2275 int exynos_gsc_connect(
2279 struct GSC_HANDLE
*gsc_handle
;
2281 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2285 if (handle
== NULL
) {
2286 ALOGE("%s::handle == NULL() fail", __func__
);
2290 exynos_mutex_lock(gsc_handle
->op_mutex
);
2292 gsc_handle
->flag_local_path
= true;
2294 if (exynos_mutex_trylock(gsc_handle
->cur_obj_mutex
) == false) {
2295 if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle
) == false) {
2296 ALOGE("%s::m_exynos_gsc_find_and_trylock_and_create() fail", __func__
);
2306 exynos_mutex_unlock(gsc_handle
->op_mutex
);
2311 int exynos_gsc_disconnect(
2315 struct GSC_HANDLE
*gsc_handle
;
2316 gsc_handle
= (struct GSC_HANDLE
*)handle
;
2320 if (handle
== NULL
) {
2321 ALOGE("%s::handle == NULL() fail", __func__
);
2325 exynos_mutex_lock(gsc_handle
->op_mutex
);
2327 gsc_handle
->flag_local_path
= false;
2329 exynos_mutex_unlock(gsc_handle
->cur_obj_mutex
);
2331 exynos_mutex_unlock(gsc_handle
->op_mutex
);