libkeymaster: Fix UniquePtr dependency
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libgscaler / libgscaler_obj.cpp
CommitLineData
e3534476
T
1/*
2 * Copyright (C) 2013 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 libgscaler_obj.cpp
20 * \brief source file for Gscaler HAL
21 * \author Sungchun Kang (sungchun.kang@samsung.com)
22 * \date 2013/06/01
23 *
24 * <b>Revision History: </b>
25 * - 2013.06.01 : Sungchun Kang (sungchun.kang@samsung.com) \n
26 * Create
27 */
28
29#include "libgscaler_obj.h"
30#include "content_protect.h"
31
32int CGscaler::m_gsc_output_create(void *handle, int dev_num, int out_mode)
33{
34 Exynos_gsc_In();
35
36 struct media_device *media0;
37 struct media_entity *gsc_sd_entity;
38 struct media_entity *gsc_vd_entity;
39 struct media_entity *sink_sd_entity;
40 struct media_link *links;
41 char node[32];
42 char devname[32];
43 unsigned int cap;
44 int i;
45 int fd = 0;
46 CGscaler* gsc = GetGscaler(handle);
47 if (gsc == NULL) {
48 ALOGE("%s::handle == NULL() fail", __func__);
49 return -1;
50 }
51
52 if ((out_mode != GSC_OUT_FIMD) &&
53 (out_mode != GSC_OUT_TV))
54 return -1;
55
56 gsc->out_mode = out_mode;
57 /* GSCX => FIMD_WINX : arbitrary linking is not allowed */
58 if ((out_mode == GSC_OUT_FIMD) &&
59#ifndef USES_ONLY_GSC0_GSC1
60 (dev_num > 2))
61#else
62 (dev_num > 1))
63#endif
64 return -1;
65
66 /* media0 */
67 snprintf(node, sizeof(node), "%s%d", PFX_NODE_MEDIADEV, 0);
68 media0 = exynos_media_open(node);
69 if (media0 == NULL) {
70 ALOGE("%s::exynos_media_open failed (node=%s)", __func__, node);
71 return false;
72 }
73 gsc->mdev.media0 = media0;
74
75 /* Get the sink subdev entity by name and make the node of sink subdev*/
76 if (out_mode == GSC_OUT_FIMD)
77 snprintf(devname, sizeof(devname), PFX_FIMD_ENTITY, dev_num);
78 else
79 snprintf(devname, sizeof(devname), PFX_MXR_ENTITY, 0);
80
81 sink_sd_entity = exynos_media_get_entity_by_name(media0, devname,
82 strlen(devname));
83 if (!sink_sd_entity) {
84 ALOGE("%s:: failed to get the sink sd entity", __func__);
85 goto gsc_output_err;
86 }
87 gsc->mdev.sink_sd_entity = sink_sd_entity;
88
89 sink_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
90 if (sink_sd_entity->fd < 0) {
91 ALOGE("%s:: failed to open sink subdev node", __func__);
92 goto gsc_output_err;
93 }
94
95 /* get GSC video dev & sub dev entity by name*/
96#if defined(USES_DT)
97 switch (dev_num) {
98 case 0:
99 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY0);
100 break;
101 case 1:
102 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY1);
103 break;
104 case 2:
105 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY2);
106 break;
107 }
108#else
109 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY, dev_num);
110#endif
111 gsc_vd_entity = exynos_media_get_entity_by_name(media0, devname,
112 strlen(devname));
113 if (!gsc_vd_entity) {
114 ALOGE("%s:: failed to get the gsc vd entity", __func__);
115 goto gsc_output_err;
116 }
117 gsc->mdev.gsc_vd_entity = gsc_vd_entity;
118
119 snprintf(devname, sizeof(devname), PFX_GSC_SUBDEV_ENTITY, dev_num);
120 gsc_sd_entity = exynos_media_get_entity_by_name(media0, devname,
121 strlen(devname));
122 if (!gsc_sd_entity) {
123 ALOGE("%s:: failed to get the gsc sd entity", __func__);
124 goto gsc_output_err;
125 }
126 gsc->mdev.gsc_sd_entity = gsc_sd_entity;
127
128 /* gsc sub-dev open */
129 snprintf(devname, sizeof(devname), PFX_GSC_SUBDEV_ENTITY, dev_num);
130 gsc_sd_entity->fd = exynos_subdev_open_devname(devname, O_RDWR);
131 if (gsc_sd_entity->fd < 0) {
132 ALOGE("%s: gsc sub-dev open fail", __func__);
133 goto gsc_output_err;
134 }
135
136 /* setup link : GSC : video device --> sub device */
137 for (i = 0; i < (int) gsc_vd_entity->num_links; i++) {
138 links = &gsc_vd_entity->links[i];
139
140 if (links == NULL ||
141 links->source->entity != gsc_vd_entity ||
142 links->sink->entity != gsc_sd_entity) {
143 continue;
144 } else if (exynos_media_setup_link(media0, links->source,
145 links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
146 ALOGE("%s::exynos_media_setup_link \
147 [src.entity=%d->sink.entity=%d] failed",
148 __func__, links->source->entity->info.id,
149 links->sink->entity->info.id);
150 return -1;
151 }
152 }
153
154 /* setup link : GSC: sub device --> sink device */
155 for (i = 0; i < (int) gsc_sd_entity->num_links; i++) {
156 links = &gsc_sd_entity->links[i];
157
158 if (links == NULL || links->source->entity != gsc_sd_entity ||
159 links->sink->entity != sink_sd_entity) {
160 continue;
161 } else if (exynos_media_setup_link(media0, links->source,
162 links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
163 ALOGE("%s::exynos_media_setup_link \
164 [src.entity=%d->sink.entity=%d] failed",
165 __func__, links->source->entity->info.id,
166 links->sink->entity->info.id);
167 return -1;
168 }
169 }
170
171 /* gsc video-dev open */
172#if defined(USES_DT)
173 switch (dev_num) {
174 case 0:
175 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY0);
176 break;
177 case 1:
178 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY1);
179 break;
180 case 2:
181 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY2);
182 break;
183 }
184#else
185 snprintf(devname, sizeof(devname), PFX_GSC_VIDEODEV_ENTITY, dev_num);
186#endif
187 gsc_vd_entity->fd = exynos_v4l2_open_devname(devname, O_RDWR);
188 if (gsc_vd_entity->fd < 0) {
189 ALOGE("%s: gsc video-dev open fail", __func__);
190 goto gsc_output_err;
191 }
192
193 cap = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
194
195 if (exynos_v4l2_querycap(gsc_vd_entity->fd, cap) == false) {
196 ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
197 goto gsc_output_err;
198 }
199
200 Exynos_gsc_Out();
201
202 return 0;
203
204gsc_output_err:
205 gsc->m_gsc_out_destroy(handle);
206
207 return -1;
208}
209
210int CGscaler::m_gsc_out_stop(void *handle)
211{
212 Exynos_gsc_In();
213
214 struct v4l2_requestbuffers reqbuf;
215 CGscaler* gsc = GetGscaler(handle);
216 if (gsc == NULL) {
217 ALOGE("%s::handle == NULL() fail", __func__);
218 return -1;
219 }
220
221 if (gsc->src_info.stream_on == false) {
222 /* to handle special scenario.*/
223 gsc->src_info.qbuf_cnt = 0;
224 ALOGD("%s::GSC is already stopped", __func__);
225 goto SKIP_STREAMOFF;
226 }
227 gsc->src_info.qbuf_cnt = 0;
228 gsc->src_info.stream_on = false;
229
230 if (exynos_v4l2_streamoff(gsc->mdev.gsc_vd_entity->fd,
231 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
232 ALOGE("%s::stream off failed", __func__);
233 return -1;
234 }
235
236SKIP_STREAMOFF:
237 Exynos_gsc_Out();
238
239 return 0;
240}
241
242bool CGscaler::m_gsc_out_destroy(void *handle)
243{
244 Exynos_gsc_In();
245
246 struct media_link * links;
247 int i;
248 CGscaler* gsc = GetGscaler(handle);
249 if (gsc == NULL) {
250 ALOGE("%s::handle == NULL() fail", __func__);
251 return false;
252 }
253
254 if (gsc->src_info.stream_on == true) {
255 if (gsc->m_gsc_out_stop(gsc) < 0)
256 ALOGE("%s::m_gsc_out_stop() fail", __func__);
257
258 gsc->src_info.stream_on = false;
259 }
260
261 if (gsc->mdev.media0 && gsc->mdev.gsc_sd_entity &&
262 gsc->mdev.gsc_vd_entity && gsc->mdev.sink_sd_entity) {
263
264 /* unlink : gscaler-out --> fimd */
265 for (i = 0; i < (int) gsc->mdev.gsc_sd_entity->num_links; i++) {
266 links = &gsc->mdev.gsc_sd_entity->links[i];
267 if (links == NULL ||
268 links->source->entity != gsc->mdev.gsc_sd_entity ||
269 links->sink->entity != gsc->mdev.sink_sd_entity) {
270 continue;
271 } else if (exynos_media_setup_link(gsc->mdev.media0,
272 links->source, links->sink, 0) < 0) {
273 ALOGE("%s::exynos_media_setup_unlink \
274 [src.entity=%d->sink.entity=%d] failed",
275 __func__, links->source->entity->info.id,
276 links->sink->entity->info.id);
277 }
278 }
279 }
280
281 if (gsc->mdev.gsc_vd_entity && gsc->mdev.gsc_vd_entity->fd > 0) {
282 close(gsc->mdev.gsc_vd_entity->fd);
283 gsc->mdev.gsc_vd_entity->fd = -1;
284 }
285
286 if (gsc->mdev.gsc_sd_entity && gsc->mdev.gsc_sd_entity->fd > 0) {
287 close(gsc->mdev.gsc_sd_entity->fd);
288 gsc->mdev.gsc_sd_entity->fd = -1;
289 }
290
291 if (gsc->mdev.sink_sd_entity && gsc->mdev.sink_sd_entity->fd > 0) {
292 close(gsc->mdev.sink_sd_entity->fd);
293 gsc->mdev.sink_sd_entity->fd = -1;
294 }
295
296 if (gsc->mdev.media0)
297 exynos_media_close(gsc->mdev.media0);
298
299 gsc->mdev.media0 = NULL;
300 gsc->mdev.gsc_sd_entity = NULL;
301 gsc->mdev.gsc_vd_entity = NULL;
302 gsc->mdev.sink_sd_entity = NULL;
303
304 Exynos_gsc_Out();
305 return true;
306}
307
308int CGscaler::m_gsc_m2m_create(int dev)
309{
310 Exynos_gsc_In();
311
312 int fd = 0;
313 int video_node_num;
314 unsigned int cap;
315 char node[32];
316
317 switch(dev) {
318 case 0:
319 video_node_num = NODE_NUM_GSC_0;
320 break;
321 case 1:
322 video_node_num = NODE_NUM_GSC_1;
323 break;
324#ifndef USES_ONLY_GSC0_GSC1
325 case 2:
326 video_node_num = NODE_NUM_GSC_2;
327 break;
328 case 3:
329 video_node_num = NODE_NUM_GSC_3;
330 break;
331#endif
332 default:
333 ALOGE("%s::unexpected dev(%d) fail", __func__, dev);
334 return -1;
335 break;
336 }
337
338 snprintf(node, sizeof(node), "%s%d", PFX_NODE_GSC, video_node_num);
339 fd = exynos_v4l2_open(node, O_RDWR);
340 if (fd < 0) {
341 ALOGE("%s::exynos_v4l2_open(%s) fail", __func__, node);
342 return -1;
343 }
344
345 cap = V4L2_CAP_STREAMING |
346 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
347 V4L2_CAP_VIDEO_CAPTURE_MPLANE;
348
349 if (exynos_v4l2_querycap(fd, cap) == false) {
350 ALOGE("%s::exynos_v4l2_querycap() fail", __func__);
351 close(fd);
352 fd = 0;
353 return -1;
354 }
355
356 Exynos_gsc_Out();
357
358 return fd;
359}
360
361bool CGscaler::m_gsc_find_and_create(void *handle)
362{
363 Exynos_gsc_In();
364
365 int i = 0;
366 bool flag_find_new_gsc = false;
367 unsigned int total_sleep_time = 0;
368 CGscaler* gsc = GetGscaler(handle);
369 if (gsc == NULL) {
370 ALOGE("%s::handle == NULL() fail", __func__);
371 return false;
372 }
373
374 do {
375 for (i = 0; i < NUM_OF_GSC_HW; i++) {
376#ifndef USES_ONLY_GSC0_GSC1
377 if (i == 0 || i == 3)
378#else
379 if (i == 0)
380#endif
381 continue;
382
383 gsc->gsc_id = i;
384 gsc->gsc_fd = gsc->m_gsc_m2m_create(i);
385 if (gsc->gsc_fd < 0) {
386 gsc->gsc_fd = 0;
387 continue;
388 }
389
390 flag_find_new_gsc = true;
391 break;
392 }
393
394 if (flag_find_new_gsc == false) {
395 usleep(GSC_WAITING_TIME_FOR_TRYLOCK);
396 total_sleep_time += GSC_WAITING_TIME_FOR_TRYLOCK;
397 ALOGV("%s::waiting for the gscaler availability", __func__);
398 }
399
400 } while(flag_find_new_gsc == false
401 && total_sleep_time < MAX_GSC_WAITING_TIME_FOR_TRYLOCK);
402
403 if (flag_find_new_gsc == false)
404 ALOGE("%s::we don't have any available gsc.. fail", __func__);
405
406 Exynos_gsc_Out();
407
408 return flag_find_new_gsc;
409}
410
411bool CGscaler::m_gsc_m2m_destroy(void *handle)
412{
413 Exynos_gsc_In();
414
415 CGscaler* gsc = GetGscaler(handle);
416 if (gsc == NULL) {
417 ALOGE("%s::handle == NULL() fail", __func__);
418 return false;
419 }
420
421 /*
422 * just in case, we call stop here because we cannot afford to leave
423 * secure side protection on if things failed.
424 */
425 gsc->m_gsc_m2m_stop(handle);
426
427 if (gsc->gsc_id >= HW_SCAL0) {
428 bool ret = exynos_sc_free_and_close(gsc->scaler);
429 Exynos_gsc_Out();
430 return ret;
431 }
432
433 if (0 < gsc->gsc_fd)
434 close(gsc->gsc_fd);
435 gsc->gsc_fd = 0;
436
437 Exynos_gsc_Out();
438
439 return true;
440}
441
442int CGscaler::m_gsc_m2m_stop(void *handle)
443{
444 Exynos_gsc_In();
445
446 struct v4l2_requestbuffers req_buf;
447 int ret = 0;
448 CGscaler* gsc = GetGscaler(handle);
449 if (gsc == NULL) {
450 ALOGE("%s::handle == NULL() fail", __func__);
451 return -1;
452 }
453
454 if (!gsc->src_info.stream_on && !gsc->dst_info.stream_on) {
455 /* wasn't streaming, return success */
456 return 0;
457 } else if (gsc->src_info.stream_on != gsc->dst_info.stream_on) {
458 ALOGE("%s: invalid state, queue stream state doesn't match \
459 (%d != %d)", __func__, gsc->src_info.stream_on,
460 gsc->dst_info.stream_on);
461 ret = -1;
462 }
463
464 /*
465 * we need to plow forward on errors below to make sure that if we had
466 * turned on content protection on secure side, we turn it off.
467 *
468 * also, if we only failed to turn on one of the streams, we'll turn
469 * the other one off correctly.
470 */
471 if (gsc->src_info.stream_on == true) {
472 if (exynos_v4l2_streamoff(gsc->gsc_fd,
473 gsc->src_info.buf.buf_type) < 0) {
474 ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
475 ret = -1;
476 }
477 gsc->src_info.stream_on = false;
478 }
479
480 if (gsc->dst_info.stream_on == true) {
481 if (exynos_v4l2_streamoff(gsc->gsc_fd,
482 gsc->dst_info.buf.buf_type) < 0) {
483 ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
484 ret = -1;
485 }
486 gsc->dst_info.stream_on = false;
487 }
488
489 /* if drm is enabled */
490 if (gsc->allow_drm && gsc->protection_enabled) {
491 unsigned int protect_id = 0;
492
493 if (gsc->gsc_id == 0)
494 protect_id = CP_PROTECT_GSC0;
495 else if (gsc->gsc_id == 1)
496 protect_id = CP_PROTECT_GSC1;
497 else if (gsc->gsc_id == 2)
498 protect_id = CP_PROTECT_GSC3;
499 else if (gsc->gsc_id == 3)
500 protect_id = CP_PROTECT_GSC3;
501
502 CP_Disable_Path_Protection(protect_id);
503 gsc->protection_enabled = false;
504 }
505
506 if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
507 V4L2_CID_CONTENT_PROTECTION, 0) < 0) {
508 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
509 __func__);
510 ret = -1;
511 }
512
513 /* src: clear_buf */
514 req_buf.count = 0;
515 req_buf.type = gsc->src_info.buf.buf_type;
516 req_buf.memory = gsc->src_info.buf.mem_type;
517 if (exynos_v4l2_reqbufs(gsc->gsc_fd, &req_buf) < 0) {
518 ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
519 ret = -1;
520 }
521
522 /* dst: clear_buf */
523 req_buf.count = 0;
524 req_buf.type = gsc->dst_info.buf.buf_type;
525 req_buf.memory = gsc->dst_info.buf.mem_type;;
526 if (exynos_v4l2_reqbufs(gsc->gsc_fd, &req_buf) < 0) {
527 ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
528 ret = -1;
529 }
530
531 Exynos_gsc_Out();
532
533 return ret;
534}
535
536int CGscaler::m_gsc_m2m_run_core(void *handle)
537{
538 Exynos_gsc_In();
539
540 unsigned int rotate, hflip, vflip;
541 bool is_dirty;
542 bool is_drm;
543 CGscaler* gsc = GetGscaler(handle);
544 if (gsc == NULL) {
545 ALOGE("%s::handle == NULL() fail", __func__);
546 return -1;
547 }
548
549 is_dirty = gsc->src_info.dirty || gsc->dst_info.dirty;
550 is_drm = gsc->src_info.mode_drm;
551
552 if (is_dirty && (gsc->src_info.mode_drm != gsc->dst_info.mode_drm)) {
553 ALOGE("%s: drm mode mismatch between src and dst, \
554 gsc%d (s=%d d=%d)", __func__, gsc->gsc_id,
555 gsc->src_info.mode_drm, gsc->dst_info.mode_drm);
556 return -1;
557 } else if (is_drm && !gsc->allow_drm) {
558 ALOGE("%s: drm mode is not supported on gsc%d", __func__,
559 gsc->gsc_id);
560 return -1;
561 }
562
563 CGscaler::rotateValueHAL2GSC(gsc->dst_img.rot, &rotate, &hflip, &vflip);
564
565 if (CGscaler::m_gsc_check_src_size(&gsc->src_info.width,
566 &gsc->src_info.height, &gsc->src_info.crop_left,
567 &gsc->src_info.crop_top, &gsc->src_info.crop_width,
568 &gsc->src_info.crop_height, gsc->src_info.v4l2_colorformat,
569 (rotate == 90 || rotate == 270)) == false) {
570 ALOGE("%s::m_gsc_check_src_size() fail", __func__);
571 return -1;
572 }
573
574 if (CGscaler::m_gsc_check_dst_size(&gsc->dst_info.width,
575 &gsc->dst_info.height, &gsc->dst_info.crop_left,
576 &gsc->dst_info.crop_top, &gsc->dst_info.crop_width,
577 &gsc->dst_info.crop_height, gsc->dst_info.v4l2_colorformat,
578 gsc->dst_info.rotation) == false) {
579 ALOGE("%s::m_gsc_check_dst_size() fail", __func__);
580 return -1;
581 }
582
583 /* dequeue buffers from previous work if necessary */
584 if (gsc->src_info.stream_on == true) {
585 if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
586 ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__);
587 return -1;
588 }
589 }
590
591 /*
592 * need to set the content protection flag before doing reqbufs
593 * in set_format
594 */
595 if (is_dirty && gsc->allow_drm && is_drm) {
596 if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
597 V4L2_CID_CONTENT_PROTECTION, is_drm) < 0) {
598 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
599 return -1;
600 }
601 }
602
603 /*
604 * from this point on, we have to ensure to call stop to clean up
605 * whatever state we have set.
606 */
607
608 if (gsc->src_info.dirty) {
609 if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->src_info) == false) {
610 ALOGE("%s::m_gsc_set_format(src) fail", __func__);
611 goto done;
612 }
613 gsc->src_info.dirty = false;
614 }
615
616 if (gsc->dst_info.dirty) {
617 if (CGscaler::m_gsc_set_format(gsc->gsc_fd, &gsc->dst_info) == false) {
618 ALOGE("%s::m_gsc_set_format(dst) fail", __func__);
619 goto done;
620 }
621 gsc->dst_info.dirty = false;
622 }
623
624 /*
625 * set up csc equation property
626 */
627 if (is_dirty) {
628 if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
629 V4L2_CID_CSC_EQ_MODE, gsc->eq_auto) < 0) {
630 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
631 return -1;
632 }
633
634 if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
635 V4L2_CID_CSC_EQ, gsc->v4l2_colorspace) < 0) {
636 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
637 return -1;
638 }
639
640 if (exynos_v4l2_s_ctrl(gsc->gsc_fd,
641 V4L2_CID_CSC_RANGE, gsc->range_full) < 0) {
642 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
643 return -1;
644 }
645 }
646
647 /* if we are enabling drm, make sure to enable hw protection.
648 * Need to do this before queuing buffers so that the mmu is reserved
649 * and power domain is kept on.
650 */
651 if (is_dirty && gsc->allow_drm && is_drm) {
652 unsigned int protect_id = 0;
653
654 if (gsc->gsc_id == 0) {
655 protect_id = CP_PROTECT_GSC0;
656 } else if (gsc->gsc_id == 1) {
657 protect_id = CP_PROTECT_GSC1;
658 } else if (gsc->gsc_id == 2) {
659 protect_id = CP_PROTECT_GSC2;
660 } else if (gsc->gsc_id == 3) {
661 protect_id = CP_PROTECT_GSC3;
662 } else {
663 ALOGE("%s::invalid gscaler id %d for content protection",
664 __func__, gsc->gsc_id);
665 goto done;
666 }
667
668 if (CP_Enable_Path_Protection(protect_id) != 0) {
669 ALOGE("%s::CP_Enable_Path_Protection failed", __func__);
670 goto done;
671 }
672 gsc->protection_enabled = true;
673 }
674
675 if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->src_info) == false) {
676 ALOGE("%s::m_gsc_set_addr(src) fail", __func__);
677 goto done;
678 }
679
680 if (gsc->m_gsc_set_addr(gsc->gsc_fd, &gsc->dst_info) == false) {
681 ALOGE("%s::m_gsc_set_addr(dst) fail", __func__);
682 goto done;
683 }
684
685 if (gsc->src_info.stream_on == false) {
686 if (exynos_v4l2_streamon(gsc->gsc_fd, gsc->src_info.buf.buf_type) < 0) {
687 ALOGE("%s::exynos_v4l2_streamon(src) fail", __func__);
688 goto done;
689 }
690 gsc->src_info.stream_on = true;
691 }
692
693 if (gsc->dst_info.stream_on == false) {
694 if (exynos_v4l2_streamon(gsc->gsc_fd, gsc->dst_info.buf.buf_type) < 0) {
695 ALOGE("%s::exynos_v4l2_streamon(dst) fail", __func__);
696 goto done;
697 }
698 gsc->dst_info.stream_on = true;
699 }
700
701 Exynos_gsc_Out();
702
703 return 0;
704
705done:
706 gsc->m_gsc_m2m_stop(handle);
707 return -1;
708}
709
710bool CGscaler::m_gsc_check_src_size(
711 unsigned int *w, unsigned int *h,
712 unsigned int *crop_x, unsigned int *crop_y,
713 unsigned int *crop_w, unsigned int *crop_h,
714 int v4l2_colorformat, bool rotation)
715{
716 unsigned int minWidth, minHeight, shift = 0;
717 if (v4l2_colorformat == V4L2_PIX_FMT_RGB32 || v4l2_colorformat == V4L2_PIX_FMT_RGB565)
718 shift = 1;
719 if (rotation) {
720 minWidth = GSC_MIN_SRC_H_SIZE >> shift;
721 minHeight = GSC_MIN_SRC_W_SIZE >> shift;
722 } else {
723 minWidth = GSC_MIN_SRC_W_SIZE >> shift;
724 minHeight = GSC_MIN_SRC_H_SIZE >> shift;
725 }
726
727 if (*w < minWidth || *h < minHeight) {
728 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
729 __func__, GSC_MIN_SRC_W_SIZE, *w, GSC_MIN_SRC_H_SIZE, *h);
730 return false;
731 }
732
733 if (*crop_w < minWidth || *crop_h < minHeight) {
734 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
735 __func__, GSC_MIN_SRC_W_SIZE,* crop_w, GSC_MIN_SRC_H_SIZE, *crop_h);
736 return false;
737 }
738
739 return true;
740}
741
742bool CGscaler::m_gsc_check_dst_size(
743 unsigned int *w, unsigned int *h,
744 unsigned int *crop_x, unsigned int *crop_y,
745 unsigned int *crop_w, unsigned int *crop_h,
746 int v4l2_colorformat,
747 int rotation)
748{
749 if (*w < GSC_MIN_DST_W_SIZE || *h < GSC_MIN_DST_H_SIZE) {
750 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
751 __func__, GSC_MIN_DST_W_SIZE, *w, GSC_MIN_DST_H_SIZE, *h);
752 return false;
753 }
754
755 if (*crop_w < GSC_MIN_DST_W_SIZE || *crop_h < GSC_MIN_DST_H_SIZE) {
756 ALOGE("%s::too small size (w : %d < %d) (h : %d < %d)",
757 __func__, GSC_MIN_DST_W_SIZE,* crop_w, GSC_MIN_DST_H_SIZE, *crop_h);
758 return false;
759 }
760
761 return true;
762}
763
764
765int CGscaler::m_gsc_multiple_of_n(int number, int N)
766{
767 int result = number;
768 switch (N) {
769 case 1:
770 case 2:
771 case 4:
772 case 8:
773 case 16:
774 case 32:
775 case 64:
776 case 128:
777 case 256:
778 result = (number - (number & (N-1)));
779 break;
780 default:
781 result = number - (number % N);
782 break;
783 }
784 return result;
785}
786
787int CGscaler::m_gsc_m2m_wait_frame_done(void *handle)
788{
789 Exynos_gsc_In();
790
791 CGscaler* gsc = GetGscaler(handle);
792 if (gsc == NULL) {
793 ALOGE("%s::handle == NULL() fail", __func__);
794 return -1;
795 }
796
797 if ((gsc->src_info.stream_on == false) ||
798 (gsc->dst_info.stream_on == false)) {
799 ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
800 return -1;
801 }
802
803 if (gsc->src_info.buf.buffer_queued) {
804 if (exynos_v4l2_dqbuf(gsc->gsc_fd, &gsc->src_info.buf.buffer) < 0) {
805 ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
806 return -1;
807 }
808 gsc->src_info.buf.buffer_queued = false;
809 }
810
811 if (gsc->dst_info.buf.buffer_queued) {
812 if (exynos_v4l2_dqbuf(gsc->gsc_fd, &gsc->dst_info.buf.buffer) < 0) {
813 ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
814 return -1;
815 }
816 gsc->dst_info.buf.buffer_queued = false;
817 }
818
819 Exynos_gsc_Out();
820
821 return 0;
822}
823
824bool CGscaler::m_gsc_set_format(int fd, GscInfo *info)
825{
826 Exynos_gsc_In();
827
828 struct v4l2_requestbuffers req_buf;
829 int plane_count;
830
831 plane_count = m_gsc_get_plane_count(info->v4l2_colorformat);
832 if (plane_count < 0) {
833 ALOGE("%s::not supported v4l2_colorformat", __func__);
834 return false;
835 }
836
837 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_ROTATE, info->rotation) < 0) {
838 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_ROTATE) fail", __func__);
839 return false;
840 }
841
842 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_VFLIP, info->flip_horizontal) < 0) {
843 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_VFLIP) fail", __func__);
844 return false;
845 }
846
847 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_HFLIP, info->flip_vertical) < 0) {
848 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
849 return false;
850 }
851
852 info->format.type = info->buf.buf_type;
853 info->format.fmt.pix_mp.width = info->width;
854 info->format.fmt.pix_mp.height = info->height;
855 info->format.fmt.pix_mp.pixelformat = info->v4l2_colorformat;
856 info->format.fmt.pix_mp.field = V4L2_FIELD_ANY;
857 info->format.fmt.pix_mp.num_planes = plane_count;
858
859 if (exynos_v4l2_s_fmt(fd, &info->format) < 0) {
860 ALOGE("%s::exynos_v4l2_s_fmt() fail", __func__);
861 return false;
862 }
863
864 info->crop.type = info->buf.buf_type;
865 info->crop.c.left = info->crop_left;
866 info->crop.c.top = info->crop_top;
867 info->crop.c.width = info->crop_width;
868 info->crop.c.height = info->crop_height;
869
870 if (exynos_v4l2_s_crop(fd, &info->crop) < 0) {
871 ALOGE("%s::exynos_v4l2_s_crop() fail", __func__);
872 return false;
873 }
874
875 if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CACHEABLE, info->cacheable) < 0) {
876 ALOGE("%s::exynos_v4l2_s_ctrl() fail", __func__);
877 return false;
878 }
879
880 req_buf.count = 1;
881 req_buf.type = info->buf.buf_type;
882 req_buf.memory = info->buf.mem_type;
883 if (exynos_v4l2_reqbufs(fd, &req_buf) < 0) {
884 ALOGE("%s::exynos_v4l2_reqbufs() fail", __func__);
885 return false;
886 }
887
888 Exynos_gsc_Out();
889
890 return true;
891}
892
893unsigned int CGscaler::m_gsc_get_plane_count(int v4l_pixel_format)
894{
895 int plane_count = 0;
896
897 switch (v4l_pixel_format) {
898 case V4L2_PIX_FMT_RGB32:
899 case V4L2_PIX_FMT_BGR32:
900 case V4L2_PIX_FMT_RGB24:
901 case V4L2_PIX_FMT_RGB565:
902 case V4L2_PIX_FMT_RGB555X:
903 case V4L2_PIX_FMT_RGB444:
904 case V4L2_PIX_FMT_YUYV:
905 case V4L2_PIX_FMT_UYVY:
906 case V4L2_PIX_FMT_NV16:
907 case V4L2_PIX_FMT_NV61:
908 case V4L2_PIX_FMT_YVU420:
909 case V4L2_PIX_FMT_YUV420:
910 case V4L2_PIX_FMT_NV12:
911 case V4L2_PIX_FMT_NV21:
912 case V4L2_PIX_FMT_YUV422P:
913 plane_count = 1;
914 break;
915 case V4L2_PIX_FMT_NV12M:
916 case V4L2_PIX_FMT_NV12MT_16X16:
917 case V4L2_PIX_FMT_NV21M:
918 plane_count = 2;
919 break;
920 case V4L2_PIX_FMT_YVU420M:
921 case V4L2_PIX_FMT_YUV420M:
922 plane_count = 3;
923 break;
924 default:
925 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
926 __func__, v4l_pixel_format);
927 plane_count = -1;
928 break;
929 }
930
931 return plane_count;
932}
933
934bool CGscaler::m_gsc_set_addr(int fd, GscInfo *info)
935{
936 unsigned int i;
937 unsigned int plane_size[NUM_OF_GSC_PLANES];
938
939 CGscaler::m_gsc_get_plane_size(plane_size, info->width,
940 info->height, info->v4l2_colorformat);
941
942 info->buf.buffer.index = 0;
943 info->buf.buffer.flags = V4L2_BUF_FLAG_USE_SYNC;
944 info->buf.buffer.type = info->buf.buf_type;
945 info->buf.buffer.memory = info->buf.mem_type;
946 info->buf.buffer.m.planes = info->buf.planes;
947 info->buf.buffer.length = info->format.fmt.pix_mp.num_planes;
948 info->buf.buffer.reserved = info->acquireFenceFd;
949
950 for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) {
951 if (info->buf.buffer.memory == V4L2_MEMORY_DMABUF)
952 info->buf.buffer.m.planes[i].m.fd = (int)info->buf.addr[i];
953 else
954 info->buf.buffer.m.planes[i].m.userptr =
955 (unsigned long)info->buf.addr[i];
956 info->buf.buffer.m.planes[i].length = plane_size[i];
957 info->buf.buffer.m.planes[i].bytesused = 0;
958 }
959
960 if (exynos_v4l2_qbuf(fd, &info->buf.buffer) < 0) {
961 ALOGE("%s::exynos_v4l2_qbuf() fail", __func__);
962 return false;
963 }
964 info->buf.buffer_queued = true;
965
966 info->releaseFenceFd = info->buf.buffer.reserved;
967
968 return true;
969}
970
971unsigned int CGscaler::m_gsc_get_plane_size(
972 unsigned int *plane_size,
973 unsigned int width,
974 unsigned int height,
975 int v4l_pixel_format)
976{
977 switch (v4l_pixel_format) {
978 /* 1 plane */
979 case V4L2_PIX_FMT_RGB32:
980 case V4L2_PIX_FMT_BGR32:
981 plane_size[0] = width * height * 4;
982 plane_size[1] = 0;
983 plane_size[2] = 0;
984 break;
985 case V4L2_PIX_FMT_RGB24:
986 plane_size[0] = width * height * 3;
987 plane_size[1] = 0;
988 plane_size[2] = 0;
989 break;
990 case V4L2_PIX_FMT_RGB565:
991 case V4L2_PIX_FMT_RGB555X:
992 case V4L2_PIX_FMT_RGB444:
993 case V4L2_PIX_FMT_YUYV:
994 case V4L2_PIX_FMT_UYVY:
995 plane_size[0] = width * height * 2;
996 plane_size[1] = 0;
997 plane_size[2] = 0;
998 break;
999 /* 2 planes */
1000 case V4L2_PIX_FMT_NV12M:
1001 case V4L2_PIX_FMT_NV21M:
1002 plane_size[0] = width * height;
1003 plane_size[1] = width * (height / 2);
1004 plane_size[2] = 0;
1005 break;
1006 case V4L2_PIX_FMT_NV12:
1007 case V4L2_PIX_FMT_NV21:
1008 plane_size[0] = width * height * 3 / 2;
1009 plane_size[1] = 0;
1010 plane_size[2] = 0;
1011 break;
1012 case V4L2_PIX_FMT_NV16:
1013 case V4L2_PIX_FMT_NV61:
1014 case V4L2_PIX_FMT_YUV422P:
1015 plane_size[0] = width * height * 2;
1016 plane_size[1] = 0;
1017 plane_size[2] = 0;
1018 break;
1019 case V4L2_PIX_FMT_NV12MT_16X16:
1020 plane_size[0] = ALIGN(width, 16) * ALIGN(height, 16);
1021 plane_size[1] = ALIGN(width, 16) * ALIGN(height / 2, 8);
1022 plane_size[2] = 0;
1023 break;
1024 /* 3 planes */
1025 case V4L2_PIX_FMT_YUV420M:
1026 plane_size[0] = width * height;
1027 plane_size[1] = (width / 2) * (height / 2);
1028 plane_size[2] = (width / 2) * (height / 2);
1029 break;
1030 case V4L2_PIX_FMT_YVU420:
1031 plane_size[0] = ALIGN(width, 16) * height + ALIGN(width / 2, 16) * height;
1032 plane_size[1] = 0;
1033 plane_size[2] = 0;
1034 break;
1035 case V4L2_PIX_FMT_YUV420:
1036 plane_size[0] = width * height * 3 / 2;
1037 plane_size[1] = 0;
1038 plane_size[2] = 0;
1039 break;
1040 case V4L2_PIX_FMT_YVU420M:
1041 plane_size[0] = ALIGN(width, 16) * height;
1042 plane_size[1] = ALIGN(width / 2, 16) * (height / 2);
1043 plane_size[2] = plane_size[1];
1044 break;
1045 default:
1046 ALOGE("%s::unmatched v4l_pixel_format color_space(0x%x)\n",
1047 __func__, v4l_pixel_format);
1048 return -1;
1049 }
1050
1051 return 0;
1052}
1053
1054int CGscaler::m_gsc_m2m_config(void *handle,
1055 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1056{
1057 Exynos_gsc_In();
1058
1059 int32_t src_color_space;
1060 int32_t dst_color_space;
1061 int ret;
1062 unsigned int rotate;
1063 unsigned int hflip;
1064 unsigned int vflip;
1065 CGscaler* gsc = GetGscaler(handle);
1066 if (gsc == NULL) {
1067 ALOGE("%s::handle == NULL() fail", __func__);
1068 return -1;
1069 }
1070
1071 if ((src_img->drmMode && !gsc->allow_drm) ||
1072 (src_img->drmMode != dst_img->drmMode)) {
1073 ALOGE("%s::invalid drm state request for gsc%d (s=%d d=%d)",
1074 __func__, gsc->gsc_id, src_img->drmMode, dst_img->drmMode);
1075 return -1;
1076 }
1077
1078 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1079 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1080 CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1081 exynos_gsc_set_rotation(gsc, rotate, hflip, vflip);
1082
1083 ret = exynos_gsc_set_src_format(gsc, src_img->fw, src_img->fh,
1084 src_img->x, src_img->y, src_img->w, src_img->h,
1085 src_color_space, src_img->cacheable, src_img->drmMode);
1086 if (ret < 0) {
1087 ALOGE("%s: fail: exynos_gsc_set_src_format \
1088 [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1089 __func__, src_img->fw, src_img->fh, src_img->x, src_img->y,
1090 src_img->w, src_img->h, src_color_space, src_img->rot);
1091 return -1;
1092 }
1093
1094 ret = exynos_gsc_set_dst_format(gsc, dst_img->fw, dst_img->fh,
1095 dst_img->x, dst_img->y, dst_img->w, dst_img->h,
1096 dst_color_space, dst_img->cacheable, dst_img->drmMode);
1097 if (ret < 0) {
1098 ALOGE("%s: fail: exynos_gsc_set_dst_format \
1099 [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
1100 __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y,
1101 dst_img->w, dst_img->h, src_color_space, dst_img->rot);
1102 return -1;
1103 }
1104
1105 Exynos_gsc_Out();
1106
1107 return 0;
1108}
1109
1110int CGscaler::m_gsc_out_config(void *handle,
1111 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1112{
1113 Exynos_gsc_In();
1114
1115 struct v4l2_format fmt;
1116 struct v4l2_crop crop;
1117 struct v4l2_requestbuffers reqbuf;
1118 struct v4l2_subdev_format sd_fmt;
1119 struct v4l2_subdev_crop sd_crop;
1120 int i;
1121 unsigned int rotate;
1122 unsigned int hflip;
1123 unsigned int vflip;
1124 unsigned int plane_size[NUM_OF_GSC_PLANES];
1125 bool rgb;
1126
1127 struct v4l2_rect dst_rect;
1128 int32_t src_color_space;
1129 int32_t dst_color_space;
1130 int32_t src_planes;
1131
1132 CGscaler* gsc = GetGscaler(handle);
1133 if (gsc == NULL) {
1134 ALOGE("%s::handle == NULL() fail", __func__);
1135 return -1;
1136 }
1137
1138 if (gsc->src_info.stream_on != false) {
1139 ALOGE("Error: Src is already streamed on !!!!");
1140 return -1;
1141 }
1142
1143 memcpy(&gsc->src_img, src_img, sizeof(exynos_mpp_img));
1144 memcpy(&gsc->dst_img, dst_img, sizeof(exynos_mpp_img));
1145 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1146 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1147 src_planes = m_gsc_get_plane_count(src_color_space);
1148 src_planes = (src_planes == -1) ? 1 : src_planes;
1149 rgb = get_yuv_planes(dst_color_space) == -1;
1150 CGscaler::rotateValueHAL2GSC(dst_img->rot, &rotate, &hflip, &vflip);
1151
1152 if (CGscaler::m_gsc_check_src_size(&gsc->src_img.fw,
1153 &gsc->src_img.fh, &gsc->src_img.x, &gsc->src_img.y,
1154 &gsc->src_img.w, &gsc->src_img.h, src_color_space,
1155 (rotate == 90 || rotate == 270)) == false) {
1156 ALOGE("%s::m_gsc_check_src_size() fail", __func__);
1157 return -1;
1158 }
1159
1160 /*set: src v4l2_buffer*/
1161 gsc->src_info.buf.src_buf_idx = 0;
1162 gsc->src_info.qbuf_cnt = 0;
1163 /* set format: src pad of GSC sub-dev*/
1164 sd_fmt.pad = GSCALER_SUBDEV_PAD_SOURCE;
1165 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1166 if (gsc->out_mode == GSC_OUT_FIMD) {
1167 sd_fmt.format.width = gsc->dst_img.fw;
1168 sd_fmt.format.height = gsc->dst_img.fh;
1169 } else {
1170 sd_fmt.format.width = gsc->dst_img.w;
1171 sd_fmt.format.height = gsc->dst_img.h;
1172 }
1173 sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1174 V4L2_MBUS_FMT_YUV8_1X24;
1175 if (exynos_subdev_s_fmt(gsc->mdev.gsc_sd_entity->fd, &sd_fmt) < 0) {
1176 ALOGE("%s::GSC subdev set format failed", __func__);
1177 return -1;
1178 }
1179
1180 /* set crop: src crop of GSC sub-dev*/
1181 sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
1182 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1183 if (gsc->out_mode == GSC_OUT_FIMD) {
1184 sd_crop.rect.left = gsc->dst_img.x;
1185 sd_crop.rect.top = gsc->dst_img.y;
1186 sd_crop.rect.width = gsc->dst_img.w;
1187 sd_crop.rect.height = gsc->dst_img.h;
1188 } else {
1189 sd_crop.rect.left = 0;
1190 sd_crop.rect.top = 0;
1191 sd_crop.rect.width = gsc->dst_img.w;
1192 sd_crop.rect.height = gsc->dst_img.h;
1193 }
1194
1195 /* sink pad is connected to GSC out */
1196 /* set format: sink sub-dev */
1197 if (gsc->out_mode == GSC_OUT_FIMD) {
1198 sd_fmt.pad = FIMD_SUBDEV_PAD_SINK;
1199 sd_fmt.format.width = gsc->dst_img.w;
1200 sd_fmt.format.height = gsc->dst_img.h;
1201 } else {
1202 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SINK;
1203 sd_fmt.format.width = gsc->dst_img.w + gsc->dst_img.x*2;
1204 sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
1205 }
1206
1207 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1208 sd_fmt.format.code = rgb ? V4L2_MBUS_FMT_XRGB8888_4X8_LE :
1209 V4L2_MBUS_FMT_YUV8_1X24;
1210 if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
1211 ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
1212 sd_fmt.pad);
1213 return -1;
1214 }
1215
1216 /* set crop: sink sub-dev */
1217 if (gsc->out_mode == GSC_OUT_FIMD)
1218 sd_crop.pad = FIMD_SUBDEV_PAD_SINK;
1219 else
1220 sd_crop.pad = MIXER_V_SUBDEV_PAD_SINK;
1221
1222 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1223 if (gsc->out_mode == GSC_OUT_FIMD) {
1224 sd_crop.rect.left = gsc->dst_img.x;
1225 sd_crop.rect.top = gsc->dst_img.y;
1226 sd_crop.rect.width = gsc->dst_img.w;
1227 sd_crop.rect.height = gsc->dst_img.h;
1228 } else {
1229 sd_crop.rect.left = 0;
1230 sd_crop.rect.top = 0;
1231 sd_crop.rect.width = gsc->dst_img.w;
1232 sd_crop.rect.height = gsc->dst_img.h;
1233 }
1234
1235 if (gsc->out_mode != GSC_OUT_FIMD) {
1236 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
1237 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1238 sd_fmt.format.width = gsc->dst_img.w + gsc->dst_img.x*2;
1239 sd_fmt.format.height = gsc->dst_img.h + gsc->dst_img.y*2;
1240 sd_fmt.format.code = V4L2_MBUS_FMT_XRGB8888_4X8_LE;
1241 if (exynos_subdev_s_fmt(gsc->mdev.sink_sd_entity->fd, &sd_fmt) < 0) {
1242 ALOGE("%s::sink:set format failed (PAD=%d)", __func__,
1243 sd_fmt.pad);
1244 return -1;
1245 }
1246
1247 sd_fmt.pad = MIXER_V_SUBDEV_PAD_SOURCE;
1248 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1249 sd_crop.rect.left = gsc->dst_img.x;
1250 sd_crop.rect.top = gsc->dst_img.y;
1251 sd_crop.rect.width = gsc->dst_img.w;
1252 sd_crop.rect.height = gsc->dst_img.h;
1253 if (exynos_subdev_s_crop(gsc->mdev.sink_sd_entity->fd, &sd_crop) < 0) {
1254 ALOGE("%s::sink: subdev set crop failed(PAD=%d)", __func__,
1255 sd_crop.pad);
1256 return -1;
1257 }
1258 }
1259
1260 /*set GSC ctrls */
1261 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_ROTATE,
1262 rotate) < 0) {
1263 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_ROTATE: %d) failed",
1264 __func__, rotate);
1265 return -1;
1266 }
1267
1268 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_HFLIP,
1269 vflip) < 0) {
1270 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_HFLIP: %d) failed",
1271 __func__, vflip);
1272 return -1;
1273 }
1274
1275 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd, V4L2_CID_VFLIP,
1276 hflip) < 0) {
1277 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_VFLIP: %d) failed",
1278 __func__, hflip);
1279 return -1;
1280 }
1281
1282 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
1283 V4L2_CID_CACHEABLE, 1) < 0) {
1284 ALOGE("%s:: exynos_v4l2_s_ctrl (V4L2_CID_CACHEABLE: 1) failed",
1285 __func__);
1286 return -1;
1287 }
1288
1289 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
1290 V4L2_CID_CONTENT_PROTECTION, gsc->src_img.drmMode) < 0) {
1291 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CONTENT_PROTECTION) fail",
1292 __func__);
1293 return -1;
1294 }
1295
1296 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
1297 V4L2_CID_CSC_EQ_MODE, gsc->eq_auto) < 0) {
1298 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ_MODE) fail", __func__);
1299 return -1;
1300 }
1301
1302 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
1303 V4L2_CID_CSC_EQ, gsc->v4l2_colorspace) < 0) {
1304 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_EQ) fail", __func__);
1305 return -1;
1306 }
1307
1308 if (exynos_v4l2_s_ctrl(gsc->mdev.gsc_vd_entity->fd,
1309 V4L2_CID_CSC_RANGE, gsc->range_full) < 0) {
1310 ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
1311 return -1;
1312 }
1313
1314 /* set src format :GSC video dev*/
1315 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1316 fmt.fmt.pix_mp.width = gsc->src_img.fw;
1317 fmt.fmt.pix_mp.height = gsc->src_img.fh;
1318 fmt.fmt.pix_mp.pixelformat = src_color_space;
1319 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1320 fmt.fmt.pix_mp.num_planes = src_planes;
1321
1322 if (exynos_v4l2_s_fmt(gsc->mdev.gsc_vd_entity->fd, &fmt) < 0) {
1323 ALOGE("%s::videodev set format failed", __func__);
1324 return -1;
1325 }
1326
1327 /* set src crop info :GSC video dev*/
1328 crop.type = fmt.type;
1329 crop.c.left = gsc->src_img.x;
1330 crop.c.top = gsc->src_img.y;
1331 crop.c.width = gsc->src_img.w;
1332 crop.c.height = gsc->src_img.h;
1333
1334 if (exynos_v4l2_s_crop(gsc->mdev.gsc_vd_entity->fd, &crop) < 0) {
1335 ALOGE("%s::videodev set crop failed", __func__);
1336 return -1;
1337 }
1338
1339 reqbuf.type = fmt.type;
1340 reqbuf.memory = V4L2_MEMORY_DMABUF;
1341 reqbuf.count = MAX_BUFFERS_GSCALER_OUT;
1342
1343 if (exynos_v4l2_reqbufs(gsc->mdev.gsc_vd_entity->fd, &reqbuf) < 0) {
1344 ALOGE("%s::request buffers failed", __func__);
1345 return -1;
1346 }
1347
1348 Exynos_gsc_Out();
1349
1350 return 0;
1351}
1352
1353void CGscaler::rotateValueHAL2GSC(unsigned int transform,
1354 unsigned int *rotate, unsigned int *hflip, unsigned int *vflip)
1355{
1356 int rotate_flag = transform & 0x7;
1357 *rotate = 0;
1358 *hflip = 0;
1359 *vflip = 0;
1360
1361 switch (rotate_flag) {
1362 case HAL_TRANSFORM_ROT_90:
1363 *rotate = 90;
1364 break;
1365 case HAL_TRANSFORM_ROT_180:
1366 *rotate = 180;
1367 break;
1368 case HAL_TRANSFORM_ROT_270:
1369 *rotate = 270;
1370 break;
1371 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
1372 *rotate = 90;
1373 *vflip = 1; /* set vflip to compensate the rot & flip order. */
1374 break;
1375 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
1376 *rotate = 90;
1377 *hflip = 1; /* set hflip to compensate the rot & flip order. */
1378 break;
1379 case HAL_TRANSFORM_FLIP_H:
1380 *hflip = 1;
1381 break;
1382 case HAL_TRANSFORM_FLIP_V:
1383 *vflip = 1;
1384 break;
1385 default:
1386 break;
1387 }
1388}
1389
1390int CGscaler::m_gsc_m2m_run(void *handle,
1391 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1392{
1393 Exynos_gsc_In();
1394
1395 CGscaler* gsc = GetGscaler(handle);
1396 if (gsc == NULL) {
1397 ALOGE("%s::handle == NULL() fail", __func__);
1398 return -1;
1399 }
1400 void *addr[3] = {NULL, NULL, NULL};
1401 int ret = 0;
1402
1403 addr[0] = (void *)src_img->yaddr;
1404 addr[1] = (void *)src_img->uaddr;
1405 addr[2] = (void *)src_img->vaddr;
1406 ret = exynos_gsc_set_src_addr(handle, addr, src_img->mem_type,
1407 src_img->acquireFenceFd);
1408 if (ret < 0) {
1409 ALOGE("%s::fail: exynos_gsc_set_src_addr[%x %x %x]", __func__,
1410 (unsigned int)addr[0], (unsigned int)addr[1],
1411 (unsigned int)addr[2]);
1412 return -1;
1413 }
1414
1415 addr[0] = (void *)dst_img->yaddr;
1416 addr[1] = (void *)dst_img->uaddr;
1417 addr[2] = (void *)dst_img->vaddr;
1418 ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->mem_type,
1419 dst_img->acquireFenceFd);
1420 if (ret < 0) {
1421 ALOGE("%s::fail: exynos_gsc_set_dst_addr[%x %x %x]", __func__,
1422 (unsigned int)addr[0], (unsigned int)addr[1],
1423 (unsigned int)addr[2]);
1424 return -1;
1425 }
1426
1427 ret = gsc->m_gsc_m2m_run_core(handle);
1428 if (ret < 0) {
1429 ALOGE("%s::fail: m_gsc_m2m_run_core", __func__);
1430 return -1;
1431 }
1432
1433 if (src_img->acquireFenceFd >= 0) {
1434 close(src_img->acquireFenceFd);
1435 src_img->acquireFenceFd = -1;
1436 }
1437
1438 if (dst_img->acquireFenceFd >= 0) {
1439 close(dst_img->acquireFenceFd);
1440 dst_img->acquireFenceFd = -1;
1441 }
1442
1443 src_img->releaseFenceFd = gsc->src_info.releaseFenceFd;
1444 dst_img->releaseFenceFd = gsc->dst_info.releaseFenceFd;
1445
1446 Exynos_gsc_Out();
1447
1448 return 0;
1449}
1450
1451int CGscaler::m_gsc_out_run(void *handle, exynos_mpp_img *src_img)
1452{
1453 struct v4l2_plane planes[NUM_OF_GSC_PLANES];
1454 struct v4l2_buffer buf;
1455 int32_t src_color_space;
1456 int32_t src_planes;
1457 unsigned int i;
1458 unsigned int plane_size[NUM_OF_GSC_PLANES];
1459 CGscaler* gsc = GetGscaler(handle);
1460 if (gsc == NULL) {
1461 ALOGE("%s::handle == NULL() fail", __func__);
1462 return -1;
1463 }
1464
1465 /* All buffers have been queued, dequeue one */
1466 if (gsc->src_info.qbuf_cnt == MAX_BUFFERS_GSCALER_OUT) {
1467 memset(&buf, 0, sizeof(struct v4l2_buffer));
1468 for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1469 memset(&planes[i], 0, sizeof(struct v4l2_plane));
1470
1471 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1472 buf.memory = V4L2_MEMORY_DMABUF;
1473 buf.m.planes = planes;
1474
1475 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->src_img.format);
1476 src_planes = m_gsc_get_plane_count(src_color_space);
1477 src_planes = (src_planes == -1) ? 1 : src_planes;
1478 buf.length = src_planes;
1479
1480
1481 if (exynos_v4l2_dqbuf(gsc->mdev.gsc_vd_entity->fd, &buf) < 0) {
1482 ALOGE("%s::dequeue buffer failed (index=%d)(mSrcBufNum=%d)",
1483 __func__, gsc->src_info.buf.src_buf_idx,
1484 MAX_BUFFERS_GSCALER_OUT);
1485 return -1;
1486 }
1487 gsc->src_info.qbuf_cnt--;
1488 }
1489
1490 memset(&buf, 0, sizeof(struct v4l2_buffer));
1491 for (i = 0; i < NUM_OF_GSC_PLANES; i++)
1492 memset(&planes[i], 0, sizeof(struct v4l2_plane));
1493
1494 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(gsc->src_img.format);
1495 src_planes = m_gsc_get_plane_count(src_color_space);
1496 src_planes = (src_planes == -1) ? 1 : src_planes;
1497
1498 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1499 buf.memory = V4L2_MEMORY_DMABUF;
1500 buf.flags = V4L2_BUF_FLAG_USE_SYNC;
1501 buf.length = src_planes;
1502 buf.index = gsc->src_info.buf.src_buf_idx;
1503 buf.m.planes = planes;
1504 buf.reserved = src_img->acquireFenceFd;
1505
1506 gsc->src_info.buf.addr[0] = (void*)src_img->yaddr;
1507 gsc->src_info.buf.addr[1] = (void*)src_img->uaddr;
1508 gsc->src_info.buf.addr[2] = (void*)src_img->vaddr;
1509
1510 if (CGscaler::tmp_get_plane_size(src_color_space, plane_size,
1511 gsc->src_img.fw, gsc->src_img.fh, src_planes) != true) {
1512 ALOGE("%s:get_plane_size:fail", __func__);
1513 return -1;
1514 }
1515
1516 for (i = 0; i < buf.length; i++) {
1517 buf.m.planes[i].m.fd = (int)gsc->src_info.buf.addr[i];
1518 buf.m.planes[i].length = plane_size[i];
1519 buf.m.planes[i].bytesused = plane_size[i];
1520 }
1521
1522 /* Queue the buf */
1523 if (exynos_v4l2_qbuf(gsc->mdev.gsc_vd_entity->fd, &buf) < 0) {
1524 ALOGE("%s::queue buffer failed (index=%d)(mSrcBufNum=%d)",
1525 __func__, gsc->src_info.buf.src_buf_idx,
1526 MAX_BUFFERS_GSCALER_OUT);
1527 return -1;
1528 }
1529 gsc->src_info.buf.src_buf_idx++;
1530 gsc->src_info.buf.src_buf_idx =
1531 gsc->src_info.buf.src_buf_idx % MAX_BUFFERS_GSCALER_OUT;
1532 gsc->src_info.qbuf_cnt++;
1533
1534 if (gsc->src_info.stream_on == false) {
1535 if (exynos_v4l2_streamon(gsc->mdev.gsc_vd_entity->fd,
1536 (v4l2_buf_type)buf.type) < 0) {
1537 ALOGE("%s::stream on failed", __func__);
1538 return -1;
1539 }
1540 gsc->src_info.stream_on = true;
1541 }
1542
1543 src_img->releaseFenceFd = buf.reserved;
1544 return 0;
1545}
1546
1547bool CGscaler::tmp_get_plane_size(int V4L2_PIX,
1548 unsigned int * size, unsigned int width, unsigned int height, int src_planes)
1549{
1550 unsigned int frame_ratio = 1;
1551 int src_bpp = get_yuv_bpp(V4L2_PIX);
1552 unsigned int frame_size = width * height;
1553
1554 src_planes = (src_planes == -1) ? 1 : src_planes;
1555 frame_ratio = 8 * (src_planes -1) / (src_bpp - 8);
1556
1557 switch (src_planes) {
1558 case 1:
1559 switch (V4L2_PIX) {
1560 case V4L2_PIX_FMT_BGR32:
1561 case V4L2_PIX_FMT_RGB32:
1562 size[0] = frame_size << 2;
1563 break;
1564 case V4L2_PIX_FMT_RGB565:
1565 case V4L2_PIX_FMT_NV16:
1566 case V4L2_PIX_FMT_NV61:
1567 case V4L2_PIX_FMT_YUYV:
1568 case V4L2_PIX_FMT_UYVY:
1569 case V4L2_PIX_FMT_VYUY:
1570 case V4L2_PIX_FMT_YVYU:
1571 size[0] = frame_size << 1;
1572 break;
1573 case V4L2_PIX_FMT_YUV420:
1574 case V4L2_PIX_FMT_NV12:
1575 case V4L2_PIX_FMT_NV21:
1576 case V4L2_PIX_FMT_NV21M:
1577 size[0] = (frame_size * 3) >> 1;
1578 break;
1579 case V4L2_PIX_FMT_YVU420:
1580 size[0] = frame_size + (ALIGN((width >> 1), 16) * ((height >> 1) * 2));
1581 break;
1582 default:
1583 ALOGE("%s::invalid color type (%x)", __func__, V4L2_PIX);
1584 return false;
1585 break;
1586 }
1587 size[1] = 0;
1588 size[2] = 0;
1589 break;
1590 case 2:
1591 size[0] = frame_size;
1592 size[1] = frame_size / frame_ratio;
1593 size[2] = 0;
1594 break;
1595 case 3:
1596 size[0] = frame_size;
1597 size[1] = frame_size / frame_ratio;
1598 size[2] = frame_size / frame_ratio;
1599 break;
1600 default:
1601 ALOGE("%s::invalid color foarmt", __func__);
1602 return false;
1603 break;
1604 }
1605
1606 return true;
1607}
1608
1609int CGscaler::ConfigMpp(void *handle, exynos_mpp_img *src,
1610 exynos_mpp_img *dst)
1611{
1612 return exynos_gsc_config_exclusive(handle, src, dst);
1613}
1614
1615int CGscaler::RunMpp(void *handle, exynos_mpp_img *src,
1616 exynos_mpp_img *dst)
1617{
1618 return exynos_gsc_run_exclusive(handle, src, dst);
1619}
1620
1621int CGscaler::StopMpp(void *handle)
1622{
1623 return exynos_gsc_stop_exclusive(handle);
1624}
1625
1626void CGscaler::DestroyMpp(void *handle)
1627{
1628 return exynos_gsc_destroy(handle);
1629}
1630
1631int CGscaler::SetCSCProperty(void *handle, unsigned int eqAuto,
1632 unsigned int fullRange, unsigned int colorspace)
1633{
1634 return exynos_gsc_set_csc_property(handle, eqAuto, fullRange,
1635 colorspace);
1636}
1637
1638int CGscaler::FreeMpp(void *handle)
1639{
1640 return exynos_gsc_free_and_close(handle);
1641}
1642
1643int CGscaler::SetInputCrop(void *handle,
1644 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
1645{
1646 struct v4l2_crop crop;
1647 int ret = 0;
1648 CGscaler *gsc = GetGscaler(handle);
1649 if (gsc == NULL) {
1650 ALOGE("%s::handle == NULL() fail", __func__);
1651 return -1;
1652 }
1653
1654 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1655 crop.c.left = src_img->x;
1656 crop.c.top = src_img->y;
1657 crop.c.width = src_img->w;
1658 crop.c.height = src_img->h;
1659
1660 return exynos_v4l2_s_crop(gsc->mdev.gsc_vd_entity->fd, &crop);
1661}