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.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 <linux/v4l2-subdev.h>
30
31 #include "libgscaler_obj.h"
32 #include "libgscaler_media.h"
33
exynos_gsc_create(void)34 void *exynos_gsc_create(void)
35 {
36 CGscaler *gsc = new CGscaler(GSC_M2M_MODE);
37 if (!gsc) {
38 ALOGE("%s:: failed to allocate Gscaler handle", __func__);
39 return NULL;
40 }
41 if (gsc->m_gsc_find_and_create(gsc) == false) {
42 ALOGE("%s::m_exynos_gsc_find_and_create() fail", __func__);
43 delete gsc;
44 return NULL;
45 }
46
47 return reinterpret_cast<void *>(gsc);
48 }
49
exynos_gsc_create_exclusive(int dev_num,int mode,int out_mode,int allow_drm)50 void *exynos_gsc_create_exclusive(
51 int dev_num,
52 int mode,
53 int out_mode,
54 int allow_drm)
55 {
56 Exynos_gsc_In();
57
58 if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
59 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
60 return NULL;
61 }
62
63 if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
64 CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
65 if (!gsc) {
66 ALOGE("%s:: failed to allocate Gscaler handle", __func__);
67 return NULL;
68 }
69
70 gsc->scaler = exynos_sc_create_exclusive(dev_num - HW_SCAL0,
71 allow_drm);
72 if (!gsc->scaler) {
73 delete(gsc);
74 ALOGE("%s::exynos_sc_create fail", __func__);
75 return NULL;
76 }
77 Exynos_gsc_Out();
78 return reinterpret_cast<void *>(gsc);
79 }
80
81 if ((mode < 0) || (mode >= NUM_OF_GSC_HW)) {
82 ALOGE("%s::fail:: mode is not valid(%d) ", __func__, mode);
83 return NULL;
84 }
85
86 CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
87 if (!gsc) {
88 ALOGE("%s:: failed to allocate Gscaler handle", __func__);
89 return NULL;
90 }
91
92 if (mode == GSC_M2M_MODE) {
93 gsc->gsc_fd = gsc->m_gsc_m2m_create(dev_num);
94 if (gsc->gsc_fd < 0) {
95 ALOGE("%s::m_gsc_m2m_create(%i) fail", __func__, dev_num);
96 goto err;
97 }
98 } else {
99 ALOGE("%s::Unsupported Mode(%i) fail", __func__, dev_num);
100 goto err;
101 }
102
103 Exynos_gsc_Out();
104
105 return reinterpret_cast<void *>(gsc);
106 err:
107 switch (mode) {
108 case GSC_M2M_MODE:
109 gsc->m_gsc_m2m_destroy(gsc);
110 break;
111 }
112
113 delete(gsc);
114
115 Exynos_gsc_Out();
116
117 return NULL;
118 }
119
exynos_gsc_destroy(void * handle)120 void exynos_gsc_destroy(void *handle)
121 {
122 Exynos_gsc_In();
123
124 CGscaler* gsc = GetGscaler(handle);
125 if (gsc == NULL) {
126 ALOGE("%s::handle == NULL() fail", __func__);
127 return;
128 }
129
130 if (gsc->mode == GSC_M2M_MODE)
131 gsc->m_gsc_m2m_destroy(gsc);
132
133 delete(gsc);
134
135 Exynos_gsc_Out();
136 }
137
exynos_gsc_set_csc_property(void * handle,unsigned int eq_auto,unsigned int range_full,unsigned int v4l2_colorspace)138 int exynos_gsc_set_csc_property(
139 void *handle,
140 unsigned int eq_auto,
141 unsigned int range_full,
142 unsigned int v4l2_colorspace)
143 {
144 Exynos_gsc_In();
145
146 CGscaler *gsc = GetGscaler(handle);
147 if (gsc == NULL) {
148 ALOGE("%s::handle == NULL() fail", __func__);
149 return -1;
150 }
151
152 if (gsc->gsc_id >= HW_SCAL0) {
153 int ret;
154 ret = exynos_sc_csc_exclusive(gsc->scaler,
155 range_full, v4l2_colorspace);
156 Exynos_gsc_Out();
157 return ret;
158 }
159 gsc->eq_auto = eq_auto;
160 gsc->range_full = range_full;
161 gsc->v4l2_colorspace = v4l2_colorspace;
162
163 Exynos_gsc_Out();
164
165 return 0;
166 }
167
exynos_gsc_set_src_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm)168 int exynos_gsc_set_src_format(
169 void *handle,
170 unsigned int width,
171 unsigned int height,
172 unsigned int crop_left,
173 unsigned int crop_top,
174 unsigned int crop_width,
175 unsigned int crop_height,
176 unsigned int v4l2_colorformat,
177 unsigned int cacheable,
178 unsigned int mode_drm)
179 {
180 Exynos_gsc_In();
181
182 CGscaler *gsc = GetGscaler(handle);
183 if (gsc == NULL) {
184 ALOGE("%s::handle == NULL() fail", __func__);
185 return -1;
186 }
187 gsc->src_info.width = width;
188 gsc->src_info.height = height;
189 gsc->src_info.crop_left = crop_left;
190 gsc->src_info.crop_top = crop_top;
191 gsc->src_info.crop_width = crop_width;
192 gsc->src_info.crop_height = crop_height;
193 gsc->src_info.v4l2_colorformat = v4l2_colorformat;
194 gsc->src_info.cacheable = cacheable;
195 gsc->src_info.mode_drm = mode_drm;
196 gsc->src_info.dirty = true;
197
198 Exynos_gsc_Out();
199
200 return 0;
201 }
202
exynos_gsc_set_dst_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm)203 int exynos_gsc_set_dst_format(
204 void *handle,
205 unsigned int width,
206 unsigned int height,
207 unsigned int crop_left,
208 unsigned int crop_top,
209 unsigned int crop_width,
210 unsigned int crop_height,
211 unsigned int v4l2_colorformat,
212 unsigned int cacheable,
213 unsigned int mode_drm)
214 {
215 Exynos_gsc_In();
216
217 CGscaler *gsc = GetGscaler(handle);
218 if (gsc == NULL) {
219 ALOGE("%s::handle == NULL() fail", __func__);
220 return -1;
221 }
222
223 gsc->dst_info.width = width;
224 gsc->dst_info.height = height;
225 gsc->dst_info.crop_left = crop_left;
226 gsc->dst_info.crop_top = crop_top;
227 gsc->dst_info.crop_width = crop_width;
228 gsc->dst_info.crop_height = crop_height;
229 gsc->dst_info.v4l2_colorformat = v4l2_colorformat;
230 gsc->dst_info.dirty = true;
231 gsc->dst_info.cacheable = cacheable;
232 gsc->dst_info.mode_drm = mode_drm;
233
234 Exynos_gsc_Out();
235
236 return 0;
237 }
238
exynos_gsc_set_rotation(void * handle,int rotation,int flip_horizontal,int flip_vertical)239 int exynos_gsc_set_rotation(
240 void *handle,
241 int rotation,
242 int flip_horizontal,
243 int flip_vertical)
244 {
245 CGscaler *gsc = GetGscaler(handle);
246 if (gsc == NULL) {
247 ALOGE("%s::handle == NULL() fail", __func__);
248 return -1;
249 }
250
251 int new_rotation = rotation % 360;
252
253 if (new_rotation % 90 != 0) {
254 ALOGE("%s::rotation(%d) cannot be acceptable fail", __func__,
255 rotation);
256 return -1;
257 }
258
259 if(new_rotation < 0)
260 new_rotation = -new_rotation;
261
262 gsc->dst_info.rotation = new_rotation;
263 gsc->dst_info.flip_horizontal = flip_horizontal;
264 gsc->dst_info.flip_vertical = flip_vertical;
265
266 return 0;
267 }
268
exynos_gsc_set_src_addr(void * handle,void * addr[3],int mem_type,int acquireFenceFd)269 int exynos_gsc_set_src_addr(
270 void *handle,
271 void *addr[3],
272 int mem_type,
273 int acquireFenceFd)
274 {
275 Exynos_gsc_In();
276
277 CGscaler* gsc = GetGscaler(handle);
278 if (gsc == NULL) {
279 ALOGE("%s::handle == NULL() fail", __func__);
280 return -1;
281 }
282
283 gsc->src_info.buf.addr[0] = addr[0];
284 gsc->src_info.buf.addr[1] = addr[1];
285 gsc->src_info.buf.addr[2] = addr[2];
286 gsc->src_info.acquireFenceFd = acquireFenceFd;
287 gsc->src_info.buf.mem_type = (enum v4l2_memory)mem_type;
288
289 Exynos_gsc_Out();
290
291 return 0;
292 }
293
exynos_gsc_set_dst_addr(void * handle,void * addr[3],int mem_type,int acquireFenceFd)294 int exynos_gsc_set_dst_addr(
295 void *handle,
296 void *addr[3],
297 int mem_type,
298 int acquireFenceFd)
299 {
300 Exynos_gsc_In();
301
302 CGscaler* gsc = GetGscaler(handle);
303 if (gsc == NULL) {
304 ALOGE("%s::handle == NULL() fail", __func__);
305 return -1;
306 }
307
308 gsc->dst_info.buf.addr[0] = addr[0];
309 gsc->dst_info.buf.addr[1] = addr[1];
310 gsc->dst_info.buf.addr[2] = addr[2];
311 gsc->dst_info.acquireFenceFd = acquireFenceFd;
312 gsc->dst_info.buf.mem_type = (enum v4l2_memory)mem_type;
313
314 Exynos_gsc_Out();
315
316 return 0;
317 }
318
exynos_gsc_convert(void * handle)319 int exynos_gsc_convert(void *handle)
320 {
321 Exynos_gsc_In();
322
323 int ret = -1;
324 CGscaler* gsc = GetGscaler(handle);
325 if (gsc == NULL) {
326 ALOGE("%s::handle == NULL() fail", __func__);
327 return ret;
328 }
329
330 if (gsc->m_gsc_m2m_run_core(handle) < 0) {
331 ALOGE("%s::exynos_gsc_run_core fail", __func__);
332 goto done;
333 }
334
335 if (gsc->m_gsc_m2m_wait_frame_done(handle) < 0) {
336 ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
337 goto done;
338 }
339
340 if (gsc->src_info.releaseFenceFd >= 0) {
341 close(gsc->src_info.releaseFenceFd);
342 gsc->src_info.releaseFenceFd = -1;
343 }
344
345 if (gsc->dst_info.releaseFenceFd >= 0) {
346 close(gsc->dst_info.releaseFenceFd);
347 gsc->dst_info.releaseFenceFd = -1;
348 }
349
350 if (gsc->m_gsc_m2m_stop(handle) < 0) {
351 ALOGE("%s::m_gsc_m2m_stop", __func__);
352 goto done;
353 }
354
355 ret = 0;
356
357 done:
358 Exynos_gsc_Out();
359
360 return ret;
361 }
362
exynos_gsc_subdev_s_crop(void * handle,exynos_mpp_img __UNUSED__ * src_img,exynos_mpp_img * dst_img)363 int exynos_gsc_subdev_s_crop(void *handle,
364 exynos_mpp_img __UNUSED__ *src_img, exynos_mpp_img *dst_img)
365 {
366 struct v4l2_subdev_crop sd_crop;
367 CGscaler *gsc = GetGscaler(handle);
368 if (gsc == NULL) {
369 ALOGE("%s::handle == NULL() fail", __func__);
370 return -1;
371 }
372
373 sd_crop.pad = GSCALER_SUBDEV_PAD_SOURCE;
374 sd_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
375 sd_crop.rect.left = dst_img->x;
376 sd_crop.rect.top = dst_img->y;
377 sd_crop.rect.width = dst_img->w;
378 sd_crop.rect.height = dst_img->h;
379
380 return exynos_subdev_s_crop(gsc->mdev.gsc_sd_entity->fd, &sd_crop);
381 }
382
exynos_gsc_config_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)383 int exynos_gsc_config_exclusive(void *handle,
384 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
385 {
386 Exynos_gsc_In();
387
388 int ret = 0;
389 CGscaler* gsc = GetGscaler(handle);
390 if (gsc == NULL) {
391 ALOGE("%s::handle == NULL() fail", __func__);
392 return -1;
393 }
394 if (gsc->gsc_id >= HW_SCAL0) {
395 ret = exynos_sc_config_exclusive(gsc->scaler,
396 (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
397 Exynos_gsc_Out();
398 return ret;
399 }
400
401 switch (gsc->mode) {
402 case GSC_M2M_MODE:
403 ret = gsc->m_gsc_m2m_config(handle, src_img, dst_img);
404 break;
405 case GSC_OUTPUT_MODE:
406 ret = gsc->m_gsc_out_config(handle, src_img, dst_img);
407 break;
408 case GSC_CAPTURE_MODE:
409 ret = gsc->m_gsc_cap_config(handle, src_img, dst_img);
410 break;
411 default:
412 break;
413 }
414
415 Exynos_gsc_Out();
416
417 return ret;
418 }
419
exynos_gsc_run_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img)420 int exynos_gsc_run_exclusive(void *handle,
421 exynos_mpp_img *src_img, exynos_mpp_img *dst_img)
422 {
423 Exynos_gsc_In();
424
425 int ret = 0;
426 CGscaler* gsc = GetGscaler(handle);
427 if (handle == NULL) {
428 ALOGE("%s::handle == NULL() fail", __func__);
429 return -1;
430 }
431
432 if (gsc->gsc_id >= HW_SCAL0) {
433 ret = exynos_sc_run_exclusive(gsc->scaler,
434 (exynos_sc_img *)src_img, (exynos_sc_img *)dst_img);
435 Exynos_gsc_Out();
436 return ret;
437 }
438
439 switch (gsc->mode) {
440 case GSC_M2M_MODE:
441 ret = gsc->m_gsc_m2m_run(handle, src_img, dst_img);
442 break;
443 case GSC_OUTPUT_MODE:
444 ret = gsc->m_gsc_out_run(handle, src_img);
445 break;
446 case GSC_CAPTURE_MODE:
447 ret = gsc->m_gsc_cap_run(handle, dst_img);
448 break;
449 default:
450 break;
451 }
452
453 Exynos_gsc_Out();
454
455 return ret;
456 }
457
exynos_gsc_create_blend_exclusive(int dev_num,int mode,int out_mode,int allow_drm)458 void *exynos_gsc_create_blend_exclusive(int dev_num, int mode, int out_mode,
459 int allow_drm)
460 {
461 Exynos_gsc_In();
462
463 if ((dev_num < 0) || (dev_num >= HW_SCAL_MAX)) {
464 ALOGE("%s::fail:: dev_num is not valid(%d) ", __func__, dev_num);
465 return NULL;
466 }
467
468 if ((dev_num >= NUM_OF_GSC_HW) && (dev_num < HW_SCAL_MAX)) {
469 CGscaler *gsc = new CGscaler(mode, out_mode, dev_num, allow_drm);
470 if (!gsc) {
471 ALOGE("%s:: failed to allocate Gscaler handle", __func__);
472 return NULL;
473 }
474
475 gsc->scaler = exynos_sc_create_blend_exclusive(dev_num - HW_SCAL0, allow_drm);
476 if (!gsc->scaler) {
477 Exynos_gsc_Out();
478 delete(gsc);
479 ALOGE("%s::exynos_sc_create_blend_exclusive failed", __func__);
480 return NULL;
481 }
482 Exynos_gsc_Out();
483
484 return reinterpret_cast<void *>(gsc);
485 }
486
487 Exynos_gsc_Out();
488
489 return NULL;
490 }
491
exynos_gsc_config_blend_exclusive(void * handle,exynos_mpp_img * src_img,exynos_mpp_img * dst_img,struct SrcBlendInfo * srcblendinfo)492 int exynos_gsc_config_blend_exclusive(void *handle,
493 exynos_mpp_img *src_img, exynos_mpp_img *dst_img,
494 struct SrcBlendInfo *srcblendinfo)
495 {
496 Exynos_gsc_In();
497
498 int ret = 0;
499 CGscaler* gsc = GetGscaler(handle);
500 if (gsc == NULL) {
501 ALOGE("%s::handle == NULL() fail", __func__);
502 return -1;
503 }
504 if (gsc->gsc_id >= HW_SCAL0) {
505 ret = exynos_sc_config_blend_exclusive(gsc->scaler,
506 (exynos_sc_img *)src_img,
507 (exynos_sc_img *)dst_img,
508 srcblendinfo);
509 Exynos_gsc_Out();
510 return ret;
511 }
512 Exynos_gsc_Out();
513 return ret;
514 }
515
exynos_gsc_wait_frame_done_exclusive(void * handle)516 int exynos_gsc_wait_frame_done_exclusive(void *handle)
517 {
518 Exynos_gsc_In();
519
520 int ret = 0;
521 CGscaler* gsc = GetGscaler(handle);
522 if (handle == NULL) {
523 ALOGE("%s::handle == NULL() fail", __func__);
524 return -1;
525 }
526
527 if (gsc->gsc_id >= HW_SCAL0) {
528 ret = exynos_sc_wait_frame_done_exclusive(gsc->scaler);
529 Exynos_gsc_Out();
530 return ret;
531 }
532
533 if (gsc->mode == GSC_M2M_MODE)
534 ret = gsc->m_gsc_m2m_wait_frame_done(handle);
535
536 Exynos_gsc_Out();
537
538 return ret;
539 }
540
exynos_gsc_stop_exclusive(void * handle)541 int exynos_gsc_stop_exclusive(void *handle)
542 {
543 Exynos_gsc_In();
544
545 int ret = 0;
546 CGscaler* gsc = GetGscaler(handle);
547 if (handle == NULL) {
548 ALOGE("%s::handle == NULL() fail", __func__);
549 return -1;
550 }
551
552 if (gsc->gsc_id >= HW_SCAL0) {
553 ret = exynos_sc_stop_exclusive(gsc->scaler);
554 Exynos_gsc_Out();
555 return ret;
556 }
557
558 switch (gsc->mode) {
559 case GSC_M2M_MODE:
560 ret = gsc->m_gsc_m2m_stop(handle);
561 break;
562 default:
563 break;
564 }
565
566 Exynos_gsc_Out();
567
568 return ret;
569 }
570
exynos_gsc_free_and_close(void * handle)571 int exynos_gsc_free_and_close(void *handle)
572 {
573 Exynos_gsc_In();
574
575 struct v4l2_requestbuffers reqbuf;
576 int ret = 0;
577 CGscaler* gsc = GetGscaler(handle);
578 if (gsc == NULL) {
579 ALOGE("%s::handle == NULL() fail", __func__);
580 return -1;
581 }
582
583
584 if (gsc->gsc_id >= HW_SCAL0) {
585 ret = exynos_sc_free_and_close(gsc->scaler);
586 Exynos_gsc_Out();
587 return ret;
588 }
589
590 memset(&reqbuf, 0, sizeof(struct v4l2_requestbuffers));
591 if (gsc->mode == GSC_OUTPUT_MODE)
592 reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
593 else
594 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
595
596 reqbuf.memory = V4L2_MEMORY_DMABUF;
597 reqbuf.count = 0;
598
599 if (ioctl(gsc->mdev.gsc_vd_entity->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
600 ALOGE("%s::request buffers failed", __func__);
601 return -1;
602 }
603
604 exynos_gsc_destroy(gsc);
605 Exynos_gsc_Out();
606
607 return 0;
608 }
609