blob: ab744a23682a79f08eb62d8cc00df37691d4ad47 [file] [log] [blame]
codeworkx62f02ba2012-05-20 12:00:36 +02001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright@ Samsung Electronics Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*!
19 * \file SecFimc.cpp
20 * \brief source file for Fimc HAL MODULE
21 * \author Hyunkyung, Kim(hk310.kim@samsung.com)
22 * \date 2010/10/13
23 *
24 * <b>Revision History: </b>
25 * - 2010/10/13 : Hyunkyung, Kim(hk310.kim@samsung.com) \n
26 * Initial version
27 *
28 * - 2011/11/15 : Sunmi, Lee(carrotsm.lee@samsung.com) \n
29 * Adjust V4L2 architecture \n
30 */
31
32#define LOG_TAG "libfimc"
33#include <cutils/log.h>
34
35#include "SecFimc.h"
36
37#define FIMC2_DEV_NAME "/dev/video2"
38
39//#define DEBUG_LIB_FIMC
40
41#ifdef BOARD_USE_V4L2
42#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
43#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
44#define V4L2_ROTATE V4L2_CID_ROTATE
45#else
46#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT
47#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE
48#define V4L2_ROTATE V4L2_CID_ROTATION
49#endif
50
51#define V4L2_BUF_TYPE_SRC V4L2_BUF_TYPE_OUTPUT
52#define V4L2_MEMORY_TYPE_SRC V4L2_MEMORY_USERPTR
53#ifdef BOARD_USE_V4L2
54#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_CAPTURE
55#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_MMAP
56#else
57#define V4L2_BUF_TYPE_DST V4L2_BUF_TYPE_VIDEO_OVERLAY
58#define V4L2_MEMORY_TYPE_DST V4L2_MEMORY_USERPTR
59#endif
60
61struct yuv_fmt_list yuv_list[] = {
62 { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 },
63#ifdef BOARD_USE_V4L2
64 { "V4L2_PIX_FMT_NV12M", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12M, 12, 2 },
65 { "V4L2_PIX_FMT_NV12MT", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12MT, 12, 2 },
66#endif
67 { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 },
68 { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 },
69 { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 },
70 { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 },
71#ifdef BOARD_USE_V4L2
72 { "V4L2_PIX_FMT_YUV420M", "YUV420/3P", V4L2_PIX_FMT_YUV420M, 12, 3 },
73#endif
74 { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 },
75 { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 },
76 { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 },
77 { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 },
78 { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 },
79 { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 },
80 { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 },
81 { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 },
82 { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 },
83 { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 },
84};
85
86#ifdef BOARD_USE_V4L2
87void dump_pixfmt_mp(struct v4l2_pix_format_mplane *pix_mp)
88{
89 LOGI("w: %d", pix_mp->width);
90 LOGI("h: %d", pix_mp->height);
91 LOGI("color: %x", pix_mp->colorspace);
92
93 switch (pix_mp->pixelformat) {
94 case V4L2_PIX_FMT_YUYV:
95 LOGI ("YUYV");
96 break;
97 case V4L2_PIX_FMT_UYVY:
98 LOGI ("UYVY");
99 break;
100 case V4L2_PIX_FMT_RGB565:
101 LOGI ("RGB565");
102 break;
103 case V4L2_PIX_FMT_RGB565X:
104 LOGI ("RGB565X");
105 break;
106 default:
107 LOGI("not supported");
108 }
109}
110#endif
111
112void dump_pixfmt(struct v4l2_pix_format *pix)
113{
114 LOGI("w: %d", pix->width);
115 LOGI("h: %d", pix->height);
116 LOGI("color: %x", pix->colorspace);
117
118 switch (pix->pixelformat) {
119 case V4L2_PIX_FMT_YUYV:
120 LOGI ("YUYV");
121 break;
122 case V4L2_PIX_FMT_UYVY:
123 LOGI ("UYVY");
124 break;
125 case V4L2_PIX_FMT_RGB565:
126 LOGI ("RGB565");
127 break;
128 case V4L2_PIX_FMT_RGB565X:
129 LOGI ("RGB565X");
130 break;
131 default:
132 LOGI("not supported");
133 }
134}
135
136void dump_crop(struct v4l2_crop *crop)
137{
138 LOGI("crop l: %d", crop->c.left);
139 LOGI("crop t: %d", crop->c.top);
140 LOGI("crop w: %d", crop->c.width);
141 LOGI("crop h: %d", crop->c.height);
142}
143
144void dump_window(struct v4l2_window *win)
145{
146 LOGI("window l: %d", win->w.left);
147 LOGI("window t: %d", win->w.top);
148 LOGI("window w: %d", win->w.width);
149 LOGI("window h: %d", win->w.height);
150}
151
152void v4l2_overlay_dump_state(int fd)
153{
154 struct v4l2_format format;
155 struct v4l2_crop crop;
156
157 format.type = V4L2_BUF_TYPE_OUTPUT;
158 if (ioctl(fd, VIDIOC_G_FMT, &format) < 0)
159 return;
160
161 LOGI("dumping driver state:");
162#ifdef BOARD_USE_V4L2
163 dump_pixfmt_mp(&format.fmt.pix_mp);
164#else
165 dump_pixfmt(&format.fmt.pix);
166#endif
167
168 crop.type = format.type;
169 if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
170 return;
171
172 LOGI("input window(crop):");
173 dump_crop(&crop);
174
175 crop.type = V4L2_BUF_TYPE_CAPTURE;
176 if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
177 return;
178
179 LOGI("output crop:");
180 dump_crop(&crop);
181
182}
183
184int fimc_v4l2_query_buf(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int buf_index, int num_plane)
185{
186 struct v4l2_buffer buf;
187 memset(&buf, 0, sizeof(struct v4l2_buffer));
188
189#ifdef BOARD_USE_V4L2
190 struct v4l2_plane planes[MAX_PLANES];
191 for (int i = 0; i < MAX_PLANES; i++)
192 memset(&planes[i], 0, sizeof(struct v4l2_plane));
193#endif
194
195 if (MAX_DST_BUFFERS <= buf_index || MAX_PLANES <= num_plane) {
196 LOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane);
197 return -1;
198 }
199
200 buf.type = type;
201 buf.memory = V4L2_MEMORY_MMAP;
202 buf.index = buf_index;
203#ifdef BOARD_USE_V4L2
204 buf.m.planes = planes;
205 buf.length = num_plane;
206#endif
207
208 if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
209 LOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
210 return -1;
211 }
212
213#ifdef BOARD_USE_V4L2
214 for (int i = 0; i < num_plane; i++) {
215 secBuf->phys.extP[i] = (unsigned int)buf.m.planes[i].cookie;
216 secBuf->size.extS[i] = buf.m.planes[i].length;
217
218 if ((secBuf->virt.extP[i] = (char *)mmap(0, buf.m.planes[i].length,
219 PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[i].m.mem_offset)) < 0) {
220 LOGE("%s::mmap failed", __func__);
221 LOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset);
222 LOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length);
223 LOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
224 LOGE("%s::paddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->phys.extP[i]);
225 return -1;
226 }
227 }
228#else
229 secBuf->size.s = buf.length;
230
231 if ((secBuf->virt.p = (char *)mmap(0, buf.length,
232 PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset)) < 0) {
233 LOGE("%s::mmap failed", __func__);
234 return -1;
235 }
236 LOGI("%s::buffers[%d] vaddr = 0x%x", __func__, buf_index, (unsigned int)secBuf->virt.p);
237#endif
238
239 return 0;
240}
241
242int fimc_v4l2_req_buf(int fd, unsigned int num_bufs, enum v4l2_buf_type type, enum v4l2_memory memory)
243{
244 struct v4l2_requestbuffers reqbuf;
245
246 reqbuf.type = type;
247 reqbuf.memory = memory;
248 reqbuf.count = num_bufs;
249
250 if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
251 LOGE("%s::VIDIOC_REQBUFS failed", __func__);
252 return -1;
253 }
254
255#ifdef DEBUG_LIB_FIMC
256 LOGI("%d buffers allocated %d requested", reqbuf.count, 4);
257#endif
258
259 if (reqbuf.count < num_bufs) {
260 LOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
261 __func__, reqbuf.count, num_bufs);
262 return -1;
263 }
264
265 return 0;
266}
267
268int fimc_v4l2_s_ctrl(int fd, int id, int value)
269{
270 struct v4l2_control vc;
271 vc.id = id;
272 vc.value = value;
273
274 if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
275 LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value);
276 return -1;
277 }
278
279 return 0;
280}
281
282int fimc_v4l2_set_fmt(int fd, enum v4l2_buf_type type, enum v4l2_field field, s5p_fimc_img_info *img_info, unsigned int addr)
283{
284 struct v4l2_framebuffer fbuf;
285 struct v4l2_format fmt;
286 struct v4l2_crop crop;
287 struct fimc_buf fimc_dst_buf;
288 struct v4l2_control vc;
289
290 fmt.type = type;
291 if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
292 LOGE("%s::VIDIOC_G_FMT failed", __func__);
293 return -1;
294 }
295
296 switch (fmt.type) {
297 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
298 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
299 fmt.fmt.pix.width = img_info->full_width;
300 fmt.fmt.pix.height = img_info->full_height;
301 fmt.fmt.pix.pixelformat = img_info->color_space;
302 fmt.fmt.pix.field = field;
303 break;
304#ifdef BOARD_USE_V4L2
305 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
306 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
307 fmt.fmt.pix_mp.width = img_info->full_width;
308 fmt.fmt.pix_mp.height = img_info->full_height;
309 fmt.fmt.pix_mp.pixelformat = img_info->color_space;
310 fmt.fmt.pix_mp.field = field;
311 fmt.fmt.pix_mp.num_planes = img_info->planes;
312 break;
313#endif
314 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
315 if (ioctl(fd, VIDIOC_G_FBUF, &fbuf) < 0) {
316 LOGE("%s::VIDIOC_G_FBUF failed", __func__);
317 return -1;
318 }
319
320 fbuf.base = (void *)addr;
321 fbuf.fmt.width = img_info->full_width;
322 fbuf.fmt.height = img_info->full_height;
323 fbuf.fmt.pixelformat = img_info->color_space;
324
325 if (ioctl(fd, VIDIOC_S_FBUF, &fbuf) < 0) {
326 LOGE("%s::VIDIOC_S_FBUF (w=%d, h=%d, color=%d) failed",
327 __func__,
328 img_info->full_width,
329 img_info->full_height,
330 img_info->color_space);
331 return -1;
332 }
333
334 fimc_dst_buf.base[0] = (unsigned int)img_info->buf_addr_phy_rgb_y;
335 fimc_dst_buf.base[1] = (unsigned int)img_info->buf_addr_phy_cb;
336 fimc_dst_buf.base[2] = (unsigned int)img_info->buf_addr_phy_cr;
337
338 vc.id = V4L2_CID_DST_INFO;
339 vc.value = (unsigned int)&fimc_dst_buf.base[0];
340
341 if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
342 LOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, vc.id, vc.value);
343 return -1;
344 }
345
346 fmt.fmt.win.w.left = img_info->start_x;
347 fmt.fmt.win.w.top = img_info->start_y;
348 fmt.fmt.win.w.width = img_info->width;
349 fmt.fmt.win.w.height = img_info->height;
350 break;
351 default:
352 LOGE("invalid buffer type");
353 return -1;
354 break;
355 }
356
357 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
358 LOGE("%s::VIDIOC_S_FMT failed", __func__);
359 return -1;
360 }
361
362 if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
363 crop.type = type;
364 crop.c.left = img_info->start_x;
365 crop.c.top = img_info->start_y;
366 crop.c.width = img_info->width;
367 crop.c.height = img_info->height;
368
369 if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
370 LOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
371 __func__,
372 img_info->start_x,
373 img_info->start_y,
374 img_info->width,
375 img_info->height);
376 return -1;
377 }
378 }
379
380 return 0;
381}
382
383int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
384{
385 if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
386 LOGE("%s::VIDIOC_STREAMON failed", __func__);
387 return -1;
388 }
389
390 return 0;
391}
392
393int fimc_v4l2_queue(int fd, SecBuffer *secBuf, enum v4l2_buf_type type, enum v4l2_memory memory, int index, int num_plane)
394{
395 struct v4l2_buffer buf;
396 memset(&buf, 0, sizeof(struct v4l2_buffer));
397
398#ifdef BOARD_USE_V4L2
399 struct v4l2_plane planes[MAX_PLANES];
400 for (int i = 0; i < MAX_PLANES; i++)
401 memset(&planes[i], 0, sizeof(struct v4l2_plane));
402#else
403 struct fimc_buf fimcbuf;
404#endif
405
406 buf.type = type;
407 buf.memory = memory;
408 buf.length = num_plane;
409 buf.index = index;
410#ifdef BOARD_USE_V4L2
411 buf.m.planes = planes;
412
413 for (unsigned int i = 0; i < buf.length; i++) {
414 buf.m.planes[i].length = secBuf->size.extS[i];
415 buf.m.planes[i].m.userptr = (unsigned long)secBuf->phys.extP[i];
416 }
417#else
418 for (int i = 0; i < 3 ; i++) {
419 fimcbuf.base[i] = secBuf->phys.extP[i];
420 fimcbuf.length[i] = secBuf->size.extS[i];
421 }
422
423 buf.m.userptr = (unsigned long)(&fimcbuf);
424 //buf.m.userptr = secBuf->phys.p;
425#endif
426
427 if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
428 LOGE("%s::VIDIOC_QBUF failed", __func__);
429 return -1;
430 }
431
432 return 0;
433}
434
435int fimc_v4l2_dequeue(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *index, int num_plane)
436{
437 struct v4l2_buffer buf;
438 memset(&buf, 0, sizeof(struct v4l2_buffer));
439
440#ifdef BOARD_USE_V4L2
441 struct v4l2_plane planes[MAX_PLANES];
442 for (int i = 0; i < MAX_PLANES; i++)
443 memset(&planes[i], 0, sizeof(struct v4l2_plane));
444#endif
445
446 buf.type = type;
447 buf.memory = memory;
448 buf.length = num_plane;
449#ifdef BOARD_USE_V4L2
450 buf.m.planes = planes;
451#endif
452 if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
453 LOGE("%s::VIDIOC_DQBUF failed", __func__);
454 return -1;
455 }
456 *index = buf.index;
457
458 return 0;
459}
460
461int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
462{
463 if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
464 LOGE("%s::VIDIOC_STREAMOFF failed", __func__);
465 return -1;
466 }
467
468 return 0;
469}
470
471int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory)
472{
473 struct v4l2_requestbuffers req;
474
475 req.count = 0;
476 req.type = type;
477 req.memory = memory;
478
479 if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
480 LOGE("%s::VIDIOC_REQBUFS", __func__);
481 return -1;
482 }
483
484 return 0;
485}
486
487static inline int multipleOfN(int number, int N)
488{
489 int result = number;
490 switch (N) {
491 case 1:
492 case 2:
493 case 4:
494 case 8:
495 case 16:
496 case 32:
497 case 64:
498 case 128:
499 case 256:
500 result = (number - (number & (N-1)));
501 break;
502 default:
503 result = number - (number % N);
504 break;
505 }
506 return result;
507}
508
509extern "C" SecFimc* create_instance()
510{
511 return new SecFimc;
512}
513
514extern "C" void destroy_instance(SecFimc* handle)
515{
516 if (handle != NULL)
517 delete handle;
518}
519
520SecFimc::SecFimc()
521: mFlagCreate(false)
522{
523 memset(&mFimcCap, 0, sizeof(struct v4l2_capability));
524 memset(&mS5pFimc, 0, sizeof(s5p_fimc_t));
525
526 mRotVal = 0;
527 mRealDev = -1;
528 mNumOfBuf = 0;
529 mHwVersion = 0;
530 mGlobalAlpha = 0x0;
531 mFlagStreamOn = false;
532 mFlagSetSrcParam = false;
533 mFlagSetDstParam = false;
534 mFlagGlobalAlpha = false;
535 mFlagLocalAlpha = false;
536 mFlagColorKey = false;
537 mFimcMode = 0;
538 mFd = 0;
539 mDev = 0;
540 mColorKey = 0x0;
541}
542
543SecFimc::~SecFimc()
544{
545 if (mFlagCreate == true) {
546 LOGE("%s::this is not Destroyed fail", __func__);
547 if (destroy() == false)
548 LOGE("%s::destroy failed", __func__);
549 }
550}
551
552bool SecFimc::create(enum DEV dev, enum MODE mode, int numOfBuf)
553{
554 if (mFlagCreate == true) {
555 LOGE("%s::Already Created fail", __func__);
556 return false;
557 }
558
559 char node[20];
560 struct v4l2_format fmt;
561 struct v4l2_control vc;
562 SecBuffer zeroBuf;
563
564 mDev = dev;
565 mRealDev = dev;
566
567 switch (mode) {
568 case MODE_SINGLE_BUF:
569 mFimcMode = FIMC_OVLY_NONE_SINGLE_BUF;
570 break;
571 case MODE_MULTI_BUF:
572 mFimcMode = FIMC_OVLY_NONE_MULTI_BUF;
573 break;
574 case MODE_DMA_AUTO:
575 mFimcMode = FIMC_OVLY_DMA_AUTO;
576 break;
577 default:
578 LOGE("%s::Invalid mode(%d) fail", __func__, mode);
579 mFimcMode = FIMC_OVLY_NOT_FIXED;
580 goto err;
581 break;
582 }
583
584 mNumOfBuf = numOfBuf;
585
586 for (int i = 0; i < MAX_DST_BUFFERS; i++)
587 mDstBuffer[i] = zeroBuf;
588
589#ifdef BOARD_USE_V4L2
590 switch(mDev) {
591 case DEV_0:
592 mRealDev = 0;
593 break;
594 case DEV_1:
595 mRealDev = 2;
596 break;
597 case DEV_2:
598 mRealDev = 4;
599 break;
600 case DEV_3:
601 mRealDev = 5;
602 break;
603 default:
604 LOGE("%s::invalid mDev(%d)", __func__, mDev);
605 goto err;
606 break;
607 }
608#endif
609
610 sprintf(node, "%s%d", PFX_NODE_FIMC, (int)mRealDev);
611
612 mFd = open(node, O_RDWR);
613 if (mFd < 0) {
614 LOGE("%s::open(%s) failed", __func__, node);
615 mFd = 0;
616 goto err;
617 }
618
619 /* check capability */
620 if (ioctl(mFd, VIDIOC_QUERYCAP, &mFimcCap) < 0) {
621 LOGE("%s::VIDIOC_QUERYCAP failed", __func__);
622 goto err;
623 }
624
625 if (!(mFimcCap.capabilities & V4L2_CAP_STREAMING)) {
626 LOGE("%s::%s has no streaming support", __func__, node);
627 goto err;
628 }
629
630#ifdef BOARD_USE_V4L2
631 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
632 LOGE("%s::%s is no video output mplane", __func__, node);
633 goto err;
634 }
635
636 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
637 LOGE("%s::%s is no video capture mplane", __func__, node);
638 goto err;
639 }
640#else
641 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
642 LOGE("%s::%s is no video output", __func__, node);
643 goto err;
644 }
645
646 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
647 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
648 LOGE("%s::VIDIOC_G_FMT failed", __func__);
649 goto err;
650 }
651
652 vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR;
653 vc.value = 0;
654 if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) {
655 LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR", __func__);
656 goto err;
657 }
658
659 mDstBuffer[0].phys.p = (unsigned int)vc.value;
660
661 mS5pFimc.out_buf.phys_addr = (void *)mDstBuffer[0].phys.p;
662
663 vc.id = V4L2_CID_FIMC_VERSION;
664 vc.value = 0;
665 if (ioctl(mFd, VIDIOC_G_CTRL, &vc) < 0) {
666 LOGE("%s::VIDIOC_G_CTRL - V4L2_CID_FIMC_VERSION failed, FIMC version is set with default", __func__);
667 vc.value = 0x43;
668 }
669
670 mHwVersion = vc.value;
671
672 vc.id = V4L2_CID_OVLY_MODE;
673 vc.value = mFimcMode;
674 if (ioctl(mFd, VIDIOC_S_CTRL, &vc) < 0) {
675 LOGE("%s::VIDIOC_S_CTRL - V4L2_CID_OVLY_MODE failed", __func__);
676 goto err;
677 }
678#endif
679
680 mFlagCreate = true;
681
682 return true;
683
684err :
685 if (0 < mFd)
686 close(mFd);
687 mFd = 0;
688
689 return false;
690}
691
692bool SecFimc::destroy()
693{
694 s5p_fimc_params_t *params = &(mS5pFimc.params);
695
696 if (mFlagCreate == false) {
697 LOGE("%s::Already Destroyed fail", __func__);
698 return false;
699 }
700
701 if (mFlagStreamOn == true) {
702 if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) {
703 LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
704 return false;
705 }
706#ifdef BOARD_USE_V4L2
707 if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_DST) < 0) {
708 LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
709 return false;
710 }
711#endif
712 mFlagStreamOn = false;
713 }
714
715 if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
716 LOGE("%s::fimc_v4l2_clr_buf()[src] failed", __func__);
717 return false;
718 }
719
720#ifdef BOARD_USE_V4L2
721 if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
722 LOGE("%s::fimc_v4l2_clr_buf()[dst] failed", __func__);
723 return false;
724 }
725#endif
726 if (mS5pFimc.out_buf.phys_addr != NULL) {
727 mS5pFimc.out_buf.phys_addr = NULL;
728 mS5pFimc.out_buf.length = 0;
729 }
730
731 if (0 < mFd)
732 close(mFd);
733 mFd = 0;
734
735 mFlagCreate = false;
736
737 return true;
738}
739
740bool SecFimc::flagCreate(void)
741{
742 return mFlagCreate;
743}
744
745int SecFimc::getFd(void)
746{
747 return mFd;
748}
749
750SecBuffer * SecFimc::getMemAddr(int index)
751{
752 if (mFlagCreate == false) {
753 LOGE("%s::Not yet created", __func__);
754 return false;
755 }
756
757 return &mDstBuffer[index];
758}
759
760int SecFimc::getHWVersion(void)
761{
762 if (mFlagCreate == false) {
763 LOGE("%s::Not yet created", __func__);
764 return false;
765 }
766
767 return mHwVersion;
768}
769
770bool SecFimc::setSrcParams(unsigned int width, unsigned int height,
771 unsigned int cropX, unsigned int cropY,
772 unsigned int *cropWidth, unsigned int *cropHeight,
773 int colorFormat,
774 bool forceChange)
775{
776#ifdef DEBUG_LIB_FIMC
777 LOGD("%s", __func__);
778#endif
779
780 if (mFlagCreate == false) {
781 LOGE("%s::Not yet created", __func__);
782 return false;
783 }
784
785 int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
786 if (v4l2ColorFormat < 0) {
787 LOGE("%s::not supported color format", __func__);
788 return false;
789 }
790
791 s5p_fimc_params_t *params = &(mS5pFimc.params);
792
793 unsigned int fimcWidth = *cropWidth;
794 unsigned int fimcHeight = *cropHeight;
795 int src_planes = m_getYuvPlanes(v4l2ColorFormat);
796
797 m_checkSrcSize(width, height,
798 cropX, cropY,
799 &fimcWidth, &fimcHeight,
800 v4l2ColorFormat,
801 false);
802
803 if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
804 if (forceChange == true) {
805#ifdef DEBUG_LIB_FIMC
806 LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
807 *cropWidth, *cropHeight, fimcWidth, fimcHeight);
808#endif
809 } else {
810 LOGE("%s::invalid source params", __func__);
811 return false;
812 }
813 }
814
815 if ( (params->src.full_width == width)
816 && (params->src.full_height == height)
817 && (params->src.start_x == cropX)
818 && (params->src.start_y == cropY)
819 && (params->src.width == fimcWidth)
820 && (params->src.height == fimcHeight)
821 && (params->src.color_space == (unsigned int)v4l2ColorFormat))
822 return true;
823
824 params->src.full_width = width;
825 params->src.full_height = height;
826 params->src.start_x = cropX;
827 params->src.start_y = cropY;
828 params->src.width = fimcWidth;
829 params->src.height = fimcHeight;
830 params->src.color_space = v4l2ColorFormat;
831 src_planes = (src_planes == -1) ? 1 : src_planes;
832
833 if (mFlagSetSrcParam == true) {
834 if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
835 LOGE("%s::fimc_v4l2_clr_buf_src() failed", __func__);
836 return false;
837 }
838 }
839
840 if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_SRC, V4L2_FIELD_NONE, &(params->src), 0) < 0) {
841 LOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__);
842 return false;
843 }
844
845 if (fimc_v4l2_req_buf(mFd, 1, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
846 LOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__);
847 return false;
848 }
849
850 *cropWidth = fimcWidth;
851 *cropHeight = fimcHeight;
852
853 mFlagSetSrcParam = true;
854 return true;
855}
856
857bool SecFimc::getSrcParams(unsigned int *width, unsigned int *height,
858 unsigned int *cropX, unsigned int *cropY,
859 unsigned int *cropWidth, unsigned int *cropHeight,
860 int *colorFormat)
861{
862 struct v4l2_format fmt;
863 struct v4l2_crop crop;
864
865 fmt.type = V4L2_BUF_TYPE_SRC;
866
867 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
868 LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
869 return false;
870 }
871
872 switch (fmt.type) {
873 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
874 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
875 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
876 *width = fmt.fmt.pix.width;
877 *height = fmt.fmt.pix.height;
878 *colorFormat = fmt.fmt.pix.pixelformat;
879 break;
880#ifdef BOARD_USE_V4L2
881 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
882 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
883 *width = fmt.fmt.pix_mp.width;
884 *height = fmt.fmt.pix_mp.height;
885 *colorFormat = fmt.fmt.pix_mp.pixelformat;
886 break;
887#endif
888 default:
889 LOGE("%s::Invalid buffer type", __func__);
890 return false;
891 break;
892 }
893
894 crop.type = V4L2_BUF_TYPE_SRC;
895 if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) {
896 LOGE("%s::VIDIOC_G_CROP failed", __func__);
897 return false;
898 }
899
900 *cropX = crop.c.left;
901 *cropY = crop.c.top;
902 *cropWidth = crop.c.width;
903 *cropHeight = crop.c.height;
904
905 return true;
906}
907
908bool SecFimc::setSrcAddr(unsigned int physYAddr,
909 unsigned int physCbAddr,
910 unsigned int physCrAddr,
911 int colorFormat)
912{
913#ifdef DEBUG_LIB_FIMC
914 LOGD("%s", __func__);
915#endif
916
917 if (mFlagCreate == false) {
918 LOGE("%s::Not yet created", __func__);
919 return false;
920 }
921
922 s5p_fimc_params_t *params = &(mS5pFimc.params);
923 int src_planes = m_getYuvPlanes(params->src.color_space);
924 int src_bpp = m_getYuvBpp(params->src.color_space);
925 unsigned int frame_size = params->src.full_width * params->src.full_height;
926 src_planes = (src_planes == -1) ? 1 : src_planes;
927
928 mSrcBuffer.phys.extP[0] = physYAddr;
929
930 if (colorFormat == HAL_PIXEL_FORMAT_YV12) {
931 mSrcBuffer.phys.extP[1] = physCrAddr;
932 mSrcBuffer.phys.extP[2] = physCbAddr;
933 } else {
934 mSrcBuffer.phys.extP[1] = physCbAddr;
935 mSrcBuffer.phys.extP[2] = physCrAddr;
936 }
937
938 if (2 <= src_planes && mSrcBuffer.phys.extP[1] == 0)
939 mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[0] + frame_size;
940
941 if (3 == src_planes && mSrcBuffer.phys.extP[2] == 0) {
942 if (colorFormat == HAL_PIXEL_FORMAT_YV12) {
943 if (12 == src_bpp)
944 mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 2);
945 else
946 mSrcBuffer.phys.extP[1] = mSrcBuffer.phys.extP[2] + (frame_size >> 1);
947 } else {
948 if (12 == src_bpp)
949 mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 2);
950 else
951 mSrcBuffer.phys.extP[2] = mSrcBuffer.phys.extP[1] + (frame_size >> 1);
952 }
953 }
954
955 return true;
956}
957
958bool SecFimc::setDstParams(unsigned int width, unsigned int height,
959 unsigned int cropX, unsigned int cropY,
960 unsigned int *cropWidth, unsigned int *cropHeight,
961 int colorFormat,
962 bool forceChange)
963{
964#ifdef DEBUG_LIB_FIMC
965 LOGD("%s", __func__);
966#endif
967
968 if (mFlagCreate == false) {
969 LOGE("%s::Not yet created", __func__);
970 return false;
971 }
972
973 int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
974 if (v4l2ColorFormat < 0) {
975 LOGE("%s::not supported color format", __func__);
976 return false;
977 }
978
979 s5p_fimc_params_t *params = &(mS5pFimc.params);
980
981 unsigned int fimcWidth = *cropWidth;
982 unsigned int fimcHeight = *cropHeight;
983 int dst_planes = m_getYuvPlanes(v4l2ColorFormat);
984
985 m_checkDstSize(width, height,
986 cropX, cropY,
987 &fimcWidth, &fimcHeight,
988 v4l2ColorFormat,
989 mRotVal,
990 true);
991
992 if (fimcWidth != *cropWidth || fimcHeight != *cropHeight) {
993 if (forceChange == true) {
994#ifdef DEBUG_LIB_FIMC
995 LOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
996 *cropWidth, *cropHeight, fimcWidth, fimcHeight);
997#endif
998 } else {
999 LOGE("%s::Invalid destination params", __func__);
1000 return false;
1001 }
1002 }
1003
1004 if (90 == mRotVal || 270 == mRotVal) {
1005 params->dst.full_width = height;
1006 params->dst.full_height = width;
1007
1008 if (90 == mRotVal) {
1009 params->dst.start_x = cropY;
1010 params->dst.start_y = width - (cropX + fimcWidth);
1011 } else {
1012 params->dst.start_x = height - (cropY + fimcHeight);
1013 params->dst.start_y = cropX;
1014 }
1015
1016 params->dst.width = fimcHeight;
1017 params->dst.height = fimcWidth;
1018
1019 if (0x50 != mHwVersion)
1020 params->dst.start_y += (fimcWidth - params->dst.height);
1021
1022 } else {
1023 params->dst.full_width = width;
1024 params->dst.full_height = height;
1025
1026 if (180 == mRotVal) {
1027 params->dst.start_x = width - (cropX + fimcWidth);
1028 params->dst.start_y = height - (cropY + fimcHeight);
1029 } else {
1030 params->dst.start_x = cropX;
1031 params->dst.start_y = cropY;
1032 }
1033
1034 params->dst.width = fimcWidth;
1035 params->dst.height = fimcHeight;
1036 }
1037 params->dst.color_space = v4l2ColorFormat;
1038 dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1039
1040#ifdef BOARD_USE_V4L2
1041 if (mFlagSetDstParam == true) {
1042 if (fimc_v4l2_clr_buf(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
1043 LOGE("%s::fimc_v4l2_clr_buf_dst() failed", __func__);
1044 return false;
1045 }
1046 }
1047#endif
1048
1049 if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) {
1050 LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
1051 return false;
1052 }
1053
1054 if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) {
1055 LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
1056 return false;
1057 }
1058
1059#ifdef BOARD_USE_V4L2
1060 if (fimc_v4l2_req_buf(mFd, mNumOfBuf, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST) < 0) {
1061 LOGE("%s::fimc_v4l2_req_buf()[dst] failed", __func__);
1062 return false;
1063 }
1064
1065 for (int i = 0; i < mNumOfBuf; i++) {
1066 if (fimc_v4l2_query_buf(mFd, &(mDstBuffer[i]),
1067 V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) {
1068 LOGE("%s::fimc_v4l2_query_buf() failed", __func__);
1069 }
1070 }
1071#endif
1072
1073 *cropWidth = fimcWidth;
1074 *cropHeight = fimcHeight;
1075
1076 mFlagSetDstParam = true;
1077 return true;
1078}
1079
1080bool SecFimc::getDstParams(unsigned int *width, unsigned int *height,
1081 unsigned int *cropX, unsigned int *cropY,
1082 unsigned int *cropWidth, unsigned int *cropHeight,
1083 int *colorFormat)
1084{
1085 struct v4l2_framebuffer fbuf;
1086 struct v4l2_format fmt;
1087 struct v4l2_crop crop;
1088
1089 fmt.type = V4L2_BUF_TYPE_DST;
1090 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
1091 LOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
1092 return false;
1093 }
1094 switch (fmt.type) {
1095 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1096 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1097 *width = fmt.fmt.pix.width;
1098 *height = fmt.fmt.pix.height;
1099 *colorFormat = fmt.fmt.pix.pixelformat;
1100 break;
1101#ifdef BOARD_USE_V4L2
1102 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1103 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1104 *width = fmt.fmt.pix_mp.width;
1105 *height = fmt.fmt.pix_mp.height;
1106 *colorFormat = fmt.fmt.pix_mp.pixelformat;
1107 break;
1108#endif
1109 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1110 *cropX = fmt.fmt.win.w.left;
1111 *cropY = fmt.fmt.win.w.top;
1112 *cropWidth = fmt.fmt.win.w.width;
1113 *cropHeight = fmt.fmt.win.w.height;
1114
1115 if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
1116 LOGE("%s::VIDIOC_G_FBUF failed", __func__);
1117 return false;
1118 }
1119
1120 *width = fbuf.fmt.width;
1121 *height = fbuf.fmt.height;
1122 *colorFormat = fbuf.fmt.pixelformat;
1123 break;
1124 default:
1125 LOGE("%s::Invalid buffer type", __func__);
1126 return false;
1127 break;
1128 }
1129
1130 if (fmt.type != V4L2_BUF_TYPE_VIDEO_OVERLAY) {
1131
1132 crop.type = V4L2_BUF_TYPE_DST;
1133 if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) {
1134 LOGE("%s::VIDIOC_G_CROP(crop.type : %d) failed", __func__, crop.type);
1135 return false;
1136 }
1137
1138 *cropX = crop.c.left;
1139 *cropY = crop.c.top;
1140 *cropWidth = crop.c.width;
1141 *cropHeight = crop.c.height;
1142 }
1143
1144 return true;
1145}
1146
1147bool SecFimc::setDstAddr(unsigned int physYAddr, unsigned int physCbAddr, unsigned int physCrAddr, int buf_index)
1148{
1149#ifdef DEBUG_LIB_FIMC
1150 LOGD("%s", __func__);
1151#endif
1152
1153 s5p_fimc_params_t *params = &(mS5pFimc.params);
1154
1155 if (mFlagCreate == false) {
1156 LOGE("%s::Not yet created", __func__);
1157 return false;
1158 }
1159
1160 mS5pFimc.out_buf.phys_addr = (void *)physYAddr;
1161
1162 mDstBuffer[buf_index].phys.extP[0] = physYAddr;
1163 mDstBuffer[buf_index].phys.extP[1] = physCbAddr;
1164 mDstBuffer[buf_index].phys.extP[2] = physCrAddr;
1165
1166#ifdef BOARD_USE_V4L2
1167 if (physYAddr != 0)
1168 mS5pFimc.use_ext_out_mem = 1;
1169#else
1170 params->dst.buf_addr_phy_rgb_y = physYAddr;
1171 params->dst.buf_addr_phy_cb = physCbAddr;
1172 params->dst.buf_addr_phy_cr = physCrAddr;
1173
1174 if ((physYAddr != 0)
1175 && ((unsigned int)mS5pFimc.out_buf.phys_addr != mDstBuffer[0].phys.p))
1176 mS5pFimc.use_ext_out_mem = 1;
1177
1178 if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) {
1179 LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
1180 return false;
1181 }
1182
1183 if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_DST, V4L2_FIELD_ANY, &(params->dst), (unsigned int)mS5pFimc.out_buf.phys_addr) < 0) {
1184 LOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
1185 return false;
1186 }
1187#endif
1188
1189 return true;
1190}
1191
1192bool SecFimc::setRotVal(unsigned int rotVal)
1193{
1194 struct v4l2_control vc;
1195
1196 if (mFlagCreate == false) {
1197 LOGE("%s::Not yet created", __func__);
1198 return false;
1199 }
1200
1201 if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, rotVal) < 0) {
1202 LOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE) failed", __func__);
1203 return false;
1204 }
1205
1206 mRotVal = rotVal;
1207 return true;
1208}
1209
1210bool SecFimc::setGlobalAlpha(bool enable, int alpha)
1211{
1212 struct v4l2_framebuffer fbuf;
1213 struct v4l2_format fmt;
1214
1215 if (mFlagCreate == false) {
1216 LOGE("%s::Not yet created", __func__);
1217 return false;
1218 }
1219
1220 if (mFlagStreamOn == true) {
1221 LOGE("%s::mFlagStreamOn == true", __func__);
1222 return false;
1223 }
1224
1225 if (mFlagGlobalAlpha == enable && mGlobalAlpha == alpha)
1226 return true;
1227
1228 memset(&fbuf, 0, sizeof(fbuf));
1229
1230 if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
1231 LOGE("%s::VIDIOC_G_FBUF failed", __func__);
1232 return false;
1233 }
1234
1235 if (enable)
1236 fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1237 else
1238 fbuf.flags &= ~V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1239
1240 if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) {
1241 LOGE("%s::VIDIOC_S_FBUF failed", __func__);
1242 return false;
1243 }
1244
1245 if (enable) {
1246 memset(&fmt, 0, sizeof(fmt));
1247 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
1248
1249 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
1250 LOGE("%s::VIDIOC_G_FMT failed", __func__);
1251 return false;
1252 }
1253
1254 fmt.fmt.win.global_alpha = alpha & 0xFF;
1255 if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
1256 LOGE("%s::VIDIOC_S_FMT failed", __func__);
1257 return false;
1258 }
1259 }
1260
1261 mFlagGlobalAlpha = enable;
1262 mGlobalAlpha = alpha;
1263
1264 return true;
1265
1266}
1267
1268bool SecFimc::setLocalAlpha(bool enable)
1269{
1270 if (mFlagCreate == false) {
1271 LOGE("%s::Not yet created", __func__);
1272 return false;
1273 }
1274
1275 if (mFlagStreamOn == true) {
1276 LOGE("%s::mFlagStreamOn == true", __func__);
1277 return false;
1278 }
1279
1280 if (mFlagLocalAlpha == enable)
1281 return true;
1282
1283 return true;
1284}
1285
1286bool SecFimc::setColorKey(bool enable, int colorKey)
1287{
1288 struct v4l2_framebuffer fbuf;
1289 struct v4l2_format fmt;
1290
1291 if (mFlagCreate == false) {
1292 LOGE("%s::Not yet created", __func__);
1293 return false;
1294 }
1295
1296 if (mFlagStreamOn == true) {
1297 LOGE("%s::mFlagStreamOn == true", __func__);
1298 return false;
1299 }
1300
1301 if (mFlagColorKey == enable && mColorKey == colorKey)
1302 return true;
1303
1304 memset(&fbuf, 0, sizeof(fbuf));
1305
1306 if (ioctl(mFd, VIDIOC_G_FBUF, &fbuf) < 0) {
1307 LOGE("%s::VIDIOC_G_FBUF failed", __func__);
1308 return false;
1309 }
1310
1311 if (enable)
1312 fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
1313 else
1314 fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
1315
1316 if (ioctl(mFd, VIDIOC_S_FBUF, &fbuf) < 0) {
1317 LOGE("%s::VIDIOC_S_FBUF failed", __func__);
1318 return false;
1319 }
1320
1321 if (enable) {
1322 memset(&fmt, 0, sizeof(fmt));
1323 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
1324
1325 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
1326 LOGE("%s::VIDIOC_G_FMT failed", __func__);
1327 return false;
1328 }
1329
1330 fmt.fmt.win.chromakey = colorKey & 0xFFFFFF;
1331
1332 if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0)
1333 LOGE("%s::VIDIOC_S_FMT failed", __func__);
1334 }
1335 mFlagColorKey = enable;
1336 mColorKey = colorKey;
1337 return true;
1338}
1339
1340bool SecFimc::draw(int src_index, int dst_index)
1341{
1342#ifdef DEBUG_LIB_FIMC
1343 LOGD("%s", __func__);
1344#endif
1345
1346 if (mFlagCreate == false) {
1347 LOGE("%s::Not yet created", __func__);
1348 return false;
1349 }
1350
1351 if (mFlagSetSrcParam == false) {
1352 LOGE("%s::mFlagSetSrcParam == false fail", __func__);
1353 return false;
1354 }
1355
1356 if (mFlagSetDstParam == false) {
1357 LOGE("%s::mFlagSetDstParam == false fail", __func__);
1358 return false;
1359 }
1360
1361 s5p_fimc_params_t *params = &(mS5pFimc.params);
1362 bool flagStreamOn = false;
1363 int src_planes = m_getYuvPlanes(params->src.color_space);
1364 int dst_planes = m_getYuvPlanes(params->dst.color_space);
1365 src_planes = (src_planes == -1) ? 1 : src_planes;
1366 dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1367
1368#ifdef BOARD_USE_V4L2
1369 if (mFlagStreamOn == false) {
1370 if (m_streamOn() == false) {
1371 LOGE("%s::m_streamOn failed", __func__);
1372 return false;
1373 }
1374 mFlagStreamOn = true;
1375 }
1376 if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, &dst_index, dst_planes) < 0) {
1377 LOGE("%s::fimc_v4l2_dequeue[dst](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
1378 return false;
1379 }
1380
1381 if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
1382 LOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
1383 return false;
1384 }
1385
1386 if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) {
1387 LOGE("%s::fimc_v4l2_queue[src](index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
1388 return false;
1389 }
1390
1391 if (fimc_v4l2_queue(mFd, &(mDstBuffer[dst_index]), V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, dst_index, dst_planes) < 0) {
1392 LOGE("%s::fimc_v4l2_queue[dst](index : %d) (mNumOfBuf : %d) failed", __func__, dst_index, mNumOfBuf);
1393 return false;
1394 }
1395#else
1396 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
1397 LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
1398 goto err;
1399 }
1400
1401 flagStreamOn = true;
1402
1403 if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) {
1404 LOGE("%s::fimc_v4l2_queue(index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
1405 goto err;
1406 }
1407
1408 if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
1409 LOGE("%s::fimc_v4l2_dequeue (mNumOfBuf : %d) failed", __func__, mNumOfBuf);
1410 goto err;
1411 }
1412#endif
1413
1414err :
1415#ifndef BOARD_USE_V4L2
1416 if (flagStreamOn == true) {
1417 if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) {
1418 LOGE("%s::fimc_v4l2_stream_off() failed", __func__);
1419 return false;
1420 }
1421 }
1422#endif
1423
1424 return true;
1425}
1426
1427bool SecFimc::m_streamOn()
1428{
1429#ifdef DEBUG_LIB_FIMC
1430 LOGD("%s", __func__);
1431#endif
1432
1433#ifdef BOARD_USE_V4L2
1434 s5p_fimc_params_t *params = &(mS5pFimc.params);
1435 int src_planes = m_getYuvPlanes(params->src.color_space);
1436 int dst_planes = m_getYuvPlanes(params->dst.color_space);
1437 src_planes = (src_planes == -1) ? 1 : src_planes;
1438 dst_planes = (dst_planes == -1) ? 1 : dst_planes;
1439
1440 if (params->src.color_space == V4L2_PIX_FMT_RGB32) {
1441 mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 4;
1442
1443 } else if ( (params->src.color_space == V4L2_PIX_FMT_NV12MT)
1444 || (params->src.color_space == V4L2_PIX_FMT_NV12M)) {
1445 mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width;
1446 mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 2;
1447 } else if ( (params->src.color_space == V4L2_PIX_FMT_YUV420)
1448 || (params->src.color_space == V4L2_PIX_FMT_YUV420M)) {
1449 mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width;
1450 mSrcBuffer.size.extS[1] = params->src.full_height * params->src.full_width / 4;
1451 mSrcBuffer.size.extS[2] = params->src.full_height * params->src.full_width / 4;
1452 } else {
1453 mSrcBuffer.size.extS[0] = params->src.full_height * params->src.full_width * 2;
1454 }
1455
1456 if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, 0, src_planes) < 0) {
1457 LOGE("%s::fimc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, 0, 1);
1458 return false;
1459 }
1460
1461 for (int i = 0; i < mNumOfBuf; i++) {
1462 if (fimc_v4l2_queue(mFd, &(mDstBuffer[i]),
1463 V4L2_BUF_TYPE_DST, V4L2_MEMORY_TYPE_DST, i, dst_planes) < 0) {
1464 LOGE("%s::fimc_v4l2_queue(index : %d) (mDstBufNum : %d) failed", __func__, i, mNumOfBuf);
1465 return false;
1466 }
1467 }
1468#endif
1469 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
1470 LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
1471 return false;
1472 }
1473
1474#ifdef BOARD_USE_V4L2
1475 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_DST) < 0) {
1476 LOGE("%s::fimc_v4l2_stream_on() failed", __func__);
1477 return false;
1478 }
1479#endif
1480 return true;
1481}
1482
1483bool SecFimc::m_checkSrcSize(unsigned int width, unsigned int height,
1484 unsigned int cropX, unsigned int cropY,
1485 unsigned int *cropWidth, unsigned int *cropHeight,
1486 int colorFormat,
1487 bool forceChange)
1488{
1489 bool ret = true;
1490
1491 if (8 <= height && *cropHeight < 8) {
1492 if (forceChange)
1493 *cropHeight = 8;
1494 ret = false;
1495 }
1496
1497 if (16 <= width && *cropWidth < 16) {
1498 if (forceChange)
1499 *cropWidth = 16;
1500 ret = false;
1501 }
1502
1503 if (0x50 == mHwVersion) {
1504 if (colorFormat == V4L2_PIX_FMT_YUV422P) {
1505 if (*cropHeight % 2 != 0) {
1506 if (forceChange)
1507 *cropHeight = multipleOfN(*cropHeight, 2);
1508 ret = false;
1509 }
1510 if (*cropWidth % 2 != 0) {
1511 if (forceChange)
1512 *cropWidth = multipleOfN(*cropWidth, 2);
1513 ret = false;
1514 }
1515 }
1516 } else {
1517 if (height < 8)
1518 return false;
1519
1520 if (width % 16 != 0)
1521 return false;
1522
1523 if (*cropWidth % 16 != 0) {
1524 if (forceChange)
1525 *cropWidth = multipleOfN(*cropWidth, 16);
1526 ret = false;
1527 }
1528 }
1529
1530 return ret;
1531}
1532
1533bool SecFimc::m_checkDstSize(unsigned int width, unsigned int height,
1534 unsigned int cropX, unsigned int cropY,
1535 unsigned int *cropWidth, unsigned int *cropHeight,
1536 int colorFormat, int rotVal, bool forceChange)
1537{
1538 bool ret = true;
1539 unsigned int rotWidth;
1540 unsigned int rotHeight;
1541 unsigned int *rotCropWidth;
1542 unsigned int *rotCropHeight;
1543
1544 if (rotVal == 90 || rotVal == 270) {
1545 rotWidth = height;
1546 rotHeight = width;
1547 rotCropWidth = cropHeight;
1548 rotCropHeight = cropWidth;
1549 } else {
1550 rotWidth = width;
1551 rotHeight = height;
1552 rotCropWidth = cropWidth;
1553 rotCropHeight = cropHeight;
1554 }
1555
1556 if (rotHeight < 8)
1557 return false;
1558
1559 if (rotWidth % 8 != 0)
1560 return false;
1561
1562 switch (colorFormat) {
1563 case V4L2_PIX_FMT_NV21:
1564 case V4L2_PIX_FMT_NV12:
1565 case V4L2_PIX_FMT_NV12T:
1566#ifdef BOARD_USE_V4L2
1567 case V4L2_PIX_FMT_NV12M:
1568 case V4L2_PIX_FMT_NV12MT:
1569 case V4L2_PIX_FMT_YUV420M:
1570#endif
1571 case V4L2_PIX_FMT_YUV420:
1572 if (*rotCropHeight % 2 != 0) {
1573 if (forceChange)
1574 *rotCropHeight = multipleOfN(*rotCropHeight, 2);
1575 ret = false;
1576 }
1577 }
1578 return ret;
1579}
1580
1581int SecFimc::m_widthOfFimc(int v4l2ColorFormat, int width)
1582{
1583 int newWidth = width;
1584
1585 if (0x50 == mHwVersion) {
1586 switch (v4l2ColorFormat) {
1587 /* 422 1/2/3 plane */
1588 case V4L2_PIX_FMT_YUYV:
1589 case V4L2_PIX_FMT_UYVY:
1590 case V4L2_PIX_FMT_NV61:
1591 case V4L2_PIX_FMT_NV16:
1592 case V4L2_PIX_FMT_YUV422P:
1593 /* 420 2/3 plane */
1594 case V4L2_PIX_FMT_NV21:
1595 case V4L2_PIX_FMT_NV12:
1596 case V4L2_PIX_FMT_NV12T:
1597#ifdef BOARD_USE_V4L2
1598 case V4L2_PIX_FMT_NV12MT:
1599 case V4L2_PIX_FMT_YUV420M:
1600#endif
1601 case V4L2_PIX_FMT_YUV420:
1602
1603 newWidth = multipleOfN(width, 2);
1604 break;
1605 default :
1606 break;
1607 }
1608 } else {
1609 switch (v4l2ColorFormat) {
1610 case V4L2_PIX_FMT_RGB565:
1611 newWidth = multipleOfN(width, 8);
1612 break;
1613 case V4L2_PIX_FMT_RGB32:
1614 newWidth = multipleOfN(width, 4);
1615 break;
1616 case V4L2_PIX_FMT_YUYV:
1617 case V4L2_PIX_FMT_UYVY:
1618 newWidth = multipleOfN(width, 4);
1619 break;
1620 case V4L2_PIX_FMT_NV61:
1621 case V4L2_PIX_FMT_NV16:
1622 newWidth = multipleOfN(width, 8);
1623 break;
1624 case V4L2_PIX_FMT_YUV422P:
1625 newWidth = multipleOfN(width, 16);
1626 break;
1627 case V4L2_PIX_FMT_NV21:
1628 case V4L2_PIX_FMT_NV12:
1629 case V4L2_PIX_FMT_NV12T:
1630#ifdef BOARD_USE_V4L2
1631 case V4L2_PIX_FMT_NV12MT:
1632#endif
1633 newWidth = multipleOfN(width, 8);
1634 break;
1635#ifdef BOARD_USE_V4L2
1636 case V4L2_PIX_FMT_YUV420M:
1637#endif
1638 case V4L2_PIX_FMT_YUV420:
1639 newWidth = multipleOfN(width, 16);
1640 break;
1641 default :
1642 break;
1643 }
1644 }
1645 return newWidth;
1646}
1647
1648int SecFimc::m_heightOfFimc(int v4l2ColorFormat, int height)
1649{
1650 int newHeight = height;
1651
1652 switch (v4l2ColorFormat) {
1653 case V4L2_PIX_FMT_NV21:
1654 case V4L2_PIX_FMT_NV12:
1655 case V4L2_PIX_FMT_NV12T:
1656#ifdef BOARD_USE_V4L2
1657 case V4L2_PIX_FMT_NV12MT:
1658 case V4L2_PIX_FMT_YUV420M:
1659#endif
1660 case V4L2_PIX_FMT_YUV420:
1661 newHeight = multipleOfN(height, 2);
1662 break;
1663 default :
1664 break;
1665 }
1666 return newHeight;
1667}
1668
1669int SecFimc::m_getYuvBpp(unsigned int fmt)
1670{
1671 int i, sel = -1;
1672
1673 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
1674 if (yuv_list[i].fmt == fmt) {
1675 sel = i;
1676 break;
1677 }
1678 }
1679
1680 if (sel == -1)
1681 return sel;
1682 else
1683 return yuv_list[sel].bpp;
1684}
1685
1686int SecFimc::m_getYuvPlanes(unsigned int fmt)
1687{
1688 int i, sel = -1;
1689
1690 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
1691 if (yuv_list[i].fmt == fmt) {
1692 sel = i;
1693 break;
1694 }
1695 }
1696
1697 if (sel == -1)
1698 return sel;
1699 else
1700 return yuv_list[sel].planes;
1701}