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