blob: a0e016d0b7b1ea695e2b88510d0255f391de8977 [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
Daniel Hillenbrand353fecb2012-07-22 16:14:08 +020032#define LOG_TAG "libfimc"
codeworkx62f02ba2012-05-20 12:00:36 +020033#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{
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +020089 ALOGI("w: %d", pix_mp->width);
90 ALOGI("h: %d", pix_mp->height);
91 ALOGI("color: %x", pix_mp->colorspace);
codeworkx62f02ba2012-05-20 12:00:36 +020092
93 switch (pix_mp->pixelformat) {
94 case V4L2_PIX_FMT_YUYV:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +020095 ALOGI ("YUYV");
codeworkx62f02ba2012-05-20 12:00:36 +020096 break;
97 case V4L2_PIX_FMT_UYVY:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +020098 ALOGI ("UYVY");
codeworkx62f02ba2012-05-20 12:00:36 +020099 break;
100 case V4L2_PIX_FMT_RGB565:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200101 ALOGI ("RGB565");
codeworkx62f02ba2012-05-20 12:00:36 +0200102 break;
103 case V4L2_PIX_FMT_RGB565X:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200104 ALOGI ("RGB565X");
codeworkx62f02ba2012-05-20 12:00:36 +0200105 break;
106 default:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200107 ALOGI("not supported");
codeworkx62f02ba2012-05-20 12:00:36 +0200108 }
109}
110#endif
111
112void dump_pixfmt(struct v4l2_pix_format *pix)
113{
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200114 ALOGI("w: %d", pix->width);
115 ALOGI("h: %d", pix->height);
116 ALOGI("color: %x", pix->colorspace);
codeworkx62f02ba2012-05-20 12:00:36 +0200117
118 switch (pix->pixelformat) {
119 case V4L2_PIX_FMT_YUYV:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200120 ALOGI ("YUYV");
codeworkx62f02ba2012-05-20 12:00:36 +0200121 break;
122 case V4L2_PIX_FMT_UYVY:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200123 ALOGI ("UYVY");
codeworkx62f02ba2012-05-20 12:00:36 +0200124 break;
125 case V4L2_PIX_FMT_RGB565:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200126 ALOGI ("RGB565");
codeworkx62f02ba2012-05-20 12:00:36 +0200127 break;
128 case V4L2_PIX_FMT_RGB565X:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200129 ALOGI ("RGB565X");
codeworkx62f02ba2012-05-20 12:00:36 +0200130 break;
131 default:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200132 ALOGI("not supported");
codeworkx62f02ba2012-05-20 12:00:36 +0200133 }
134}
135
136void dump_crop(struct v4l2_crop *crop)
137{
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200138 ALOGI("crop l: %d", crop->c.left);
139 ALOGI("crop t: %d", crop->c.top);
140 ALOGI("crop w: %d", crop->c.width);
141 ALOGI("crop h: %d", crop->c.height);
codeworkx62f02ba2012-05-20 12:00:36 +0200142}
143
144void dump_window(struct v4l2_window *win)
145{
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200146 ALOGI("window l: %d", win->w.left);
147 ALOGI("window t: %d", win->w.top);
148 ALOGI("window w: %d", win->w.width);
149 ALOGI("window h: %d", win->w.height);
codeworkx62f02ba2012-05-20 12:00:36 +0200150}
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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200161 ALOGI("dumping driver state:");
codeworkx62f02ba2012-05-20 12:00:36 +0200162#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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200172 ALOGI("input window(crop):");
codeworkx62f02ba2012-05-20 12:00:36 +0200173 dump_crop(&crop);
174
175 crop.type = V4L2_BUF_TYPE_CAPTURE;
176 if (ioctl(fd, VIDIOC_G_CROP, &crop) < 0)
177 return;
178
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200179 ALOGI("output crop:");
codeworkx62f02ba2012-05-20 12:00:36 +0200180 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200196 ALOGE("%s::exceed MAX! : buf_index=%d, num_plane=%d", __func__, buf_index, num_plane);
codeworkx62f02ba2012-05-20 12:00:36 +0200197 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200209 ALOGE("%s::VIDIOC_QUERYBUF failed, plane_cnt=%d", __func__, buf.length);
codeworkx62f02ba2012-05-20 12:00:36 +0200210 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200220 ALOGE("%s::mmap failed", __func__);
221 ALOGE("%s::Offset = 0x%x", __func__, buf.m.planes[i].m.mem_offset);
222 ALOGE("%s::Legnth = %d" , __func__, buf.m.planes[i].length);
223 ALOGE("%s::vaddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->virt.extP[i]);
224 ALOGE("%s::paddr[%d][%d] = 0x%x", __func__, buf_index, i, (unsigned int)secBuf->phys.extP[i]);
codeworkx62f02ba2012-05-20 12:00:36 +0200225 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200233 ALOGE("%s::mmap failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200234 return -1;
235 }
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200236 ALOGI("%s::buffers[%d] vaddr = 0x%x", __func__, buf_index, (unsigned int)secBuf->virt.p);
codeworkx62f02ba2012-05-20 12:00:36 +0200237#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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200251 ALOGE("%s::VIDIOC_REQBUFS failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200252 return -1;
253 }
254
255#ifdef DEBUG_LIB_FIMC
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200256 ALOGI("%d buffers allocated %d requested", reqbuf.count, 4);
codeworkx62f02ba2012-05-20 12:00:36 +0200257#endif
258
259 if (reqbuf.count < num_bufs) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200260 ALOGE("%s::VIDIOC_REQBUFS failed ((reqbuf.count(%d) < num_bufs(%d))",
codeworkx62f02ba2012-05-20 12:00:36 +0200261 __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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200275 ALOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, id, value);
codeworkx62f02ba2012-05-20 12:00:36 +0200276 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200292 ALOGE("%s::VIDIOC_G_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200293 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200316 ALOGE("%s::VIDIOC_G_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200317 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200326 ALOGE("%s::VIDIOC_S_FBUF (w=%d, h=%d, color=%d) failed",
codeworkx62f02ba2012-05-20 12:00:36 +0200327 __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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200342 ALOGE("%s::VIDIOC_S_CTRL (id=%d,value=%d) failed", __func__, vc.id, vc.value);
codeworkx62f02ba2012-05-20 12:00:36 +0200343 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:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200352 ALOGE("invalid buffer type");
codeworkx62f02ba2012-05-20 12:00:36 +0200353 return -1;
354 break;
355 }
356
357 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200358 ALOGE("%s::VIDIOC_S_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200359 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200370 ALOGE("%s::VIDIOC_S_CROP (x=%d, y=%d, w=%d, h=%d) failed",
codeworkx62f02ba2012-05-20 12:00:36 +0200371 __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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200386 ALOGE("%s::VIDIOC_STREAMON failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200387 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200428 ALOGE("%s::VIDIOC_QBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200429 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200453 ALOGE("%s::VIDIOC_DQBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200454 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200464 ALOGE("%s::VIDIOC_STREAMOFF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200465 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200480 ALOGE("%s::VIDIOC_REQBUFS", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200481 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200546 ALOGE("%s::this is not Destroyed fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200547 if (destroy() == false)
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200548 ALOGE("%s::destroy failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200549 }
550}
551
552bool SecFimc::create(enum DEV dev, enum MODE mode, int numOfBuf)
553{
554 if (mFlagCreate == true) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200555 ALOGE("%s::Already Created fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200556 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:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200578 ALOGE("%s::Invalid mode(%d) fail", __func__, mode);
codeworkx62f02ba2012-05-20 12:00:36 +0200579 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:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200604 ALOGE("%s::invalid mDev(%d)", __func__, mDev);
codeworkx62f02ba2012-05-20 12:00:36 +0200605 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200614 ALOGE("%s::open(%s) failed", __func__, node);
codeworkx62f02ba2012-05-20 12:00:36 +0200615 mFd = 0;
616 goto err;
617 }
618
619 /* check capability */
620 if (ioctl(mFd, VIDIOC_QUERYCAP, &mFimcCap) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200621 ALOGE("%s::VIDIOC_QUERYCAP failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200622 goto err;
623 }
624
625 if (!(mFimcCap.capabilities & V4L2_CAP_STREAMING)) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200626 ALOGE("%s::%s has no streaming support", __func__, node);
codeworkx62f02ba2012-05-20 12:00:36 +0200627 goto err;
628 }
629
630#ifdef BOARD_USE_V4L2
631 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200632 ALOGE("%s::%s is no video output mplane", __func__, node);
codeworkx62f02ba2012-05-20 12:00:36 +0200633 goto err;
634 }
635
636 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200637 ALOGE("%s::%s is no video capture mplane", __func__, node);
codeworkx62f02ba2012-05-20 12:00:36 +0200638 goto err;
639 }
640#else
641 if (!(mFimcCap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200642 ALOGE("%s::%s is no video output", __func__, node);
codeworkx62f02ba2012-05-20 12:00:36 +0200643 goto err;
644 }
645
646 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
647 if (ioctl(mFd, VIDIOC_G_FMT, &fmt) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200648 ALOGE("%s::VIDIOC_G_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200649 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200655 ALOGE("%s::VIDIOC_G_CTRL - V4L2_CID_RESERVED_MEM_BAES_ADDR", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200656 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200666 ALOGE("%s::VIDIOC_G_CTRL - V4L2_CID_FIMC_VERSION failed, FIMC version is set with default", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200667 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200675 ALOGE("%s::VIDIOC_S_CTRL - V4L2_CID_OVLY_MODE failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200676 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200697 ALOGE("%s::Already Destroyed fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200698 return false;
699 }
700
701 if (mFlagStreamOn == true) {
702 if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_SRC) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200703 ALOGE("%s::fimc_v4l2_stream_off() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200704 return false;
705 }
706#ifdef BOARD_USE_V4L2
707 if (fimc_v4l2_stream_off(mFd, V4L2_BUF_TYPE_DST) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200708 ALOGE("%s::fimc_v4l2_stream_off() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200709 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200716 ALOGE("%s::fimc_v4l2_clr_buf()[src] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200717 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200722 ALOGE("%s::fimc_v4l2_clr_buf()[dst] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200723 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200753 ALOGE("%s::Not yet created", __func__);
Dominggoes Isakhcb48f292016-12-17 17:44:32 +0100754 return NULL;
codeworkx62f02ba2012-05-20 12:00:36 +0200755 }
756
757 return &mDstBuffer[index];
758}
759
760int SecFimc::getHWVersion(void)
761{
762 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200763 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200764 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200777 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200778#endif
779
780 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200781 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200782 return false;
783 }
784
785 int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
786 if (v4l2ColorFormat < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200787 ALOGE("%s::not supported color format", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200788 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200806 ALOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
codeworkx62f02ba2012-05-20 12:00:36 +0200807 *cropWidth, *cropHeight, fimcWidth, fimcHeight);
808#endif
809 } else {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200810 ALOGE("%s::invalid source params", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200811 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200835 ALOGE("%s::fimc_v4l2_clr_buf_src() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200836 return false;
837 }
838 }
839
840 if (fimc_v4l2_set_fmt(mFd, V4L2_BUF_TYPE_SRC, V4L2_FIELD_NONE, &(params->src), 0) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200841 ALOGE("%s::fimc_v4l2_set_fmt()[src] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200842 return false;
843 }
844
845 if (fimc_v4l2_req_buf(mFd, 1, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200846 ALOGE("%s::fimc_v4l2_req_buf()[src] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200847 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200868 ALOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
codeworkx62f02ba2012-05-20 12:00:36 +0200869 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:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200889 ALOGE("%s::Invalid buffer type", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200890 return false;
891 break;
892 }
893
894 crop.type = V4L2_BUF_TYPE_SRC;
895 if (ioctl(mFd, VIDIOC_G_CROP, &crop) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200896 ALOGE("%s::VIDIOC_G_CROP failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200897 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200914 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200915#endif
916
917 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200918 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200919 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200965 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200966#endif
967
968 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200969 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200970 return false;
971 }
972
973 int v4l2ColorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(colorFormat);
974 if (v4l2ColorFormat < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200975 ALOGE("%s::not supported color format", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +0200976 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200995 ALOGD("size is changed from [w = %d, h= %d] to [w = %d, h = %d]",
codeworkx62f02ba2012-05-20 12:00:36 +0200996 *cropWidth, *cropHeight, fimcWidth, fimcHeight);
997#endif
998 } else {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200999 ALOGE("%s::Invalid destination params", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001000 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001043 ALOGE("%s::fimc_v4l2_clr_buf_dst() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001044 return false;
1045 }
1046 }
1047#endif
1048
1049 if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, mRotVal) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001050 ALOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001051 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001055 ALOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001056 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001061 ALOGE("%s::fimc_v4l2_req_buf()[dst] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001062 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001068 ALOGE("%s::fimc_v4l2_query_buf() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001069 }
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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001091 ALOGE("%s::VIDIOC_G_FMT(fmt.type : %d) failed", __func__, fmt.type);
codeworkx62f02ba2012-05-20 12:00:36 +02001092 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001116 ALOGE("%s::VIDIOC_G_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001117 return false;
1118 }
1119
1120 *width = fbuf.fmt.width;
1121 *height = fbuf.fmt.height;
1122 *colorFormat = fbuf.fmt.pixelformat;
1123 break;
1124 default:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001125 ALOGE("%s::Invalid buffer type", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001126 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001134 ALOGE("%s::VIDIOC_G_CROP(crop.type : %d) failed", __func__, crop.type);
codeworkx62f02ba2012-05-20 12:00:36 +02001135 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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001150 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001151#endif
1152
1153 s5p_fimc_params_t *params = &(mS5pFimc.params);
1154
1155 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001156 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001157 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001179 ALOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE)", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001180 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001184 ALOGE("%s::fimc_v4l2_set_fmt()[dst] failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001185 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001197 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001198 return false;
1199 }
1200
1201 if (fimc_v4l2_s_ctrl(mFd, V4L2_ROTATE, rotVal) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001202 ALOGE("%s::fimc_v4l2_s_ctrl(V4L2_ROTATE) failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001203 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001216 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001217 return false;
1218 }
1219
1220 if (mFlagStreamOn == true) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001221 ALOGE("%s::mFlagStreamOn == true", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001222 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001231 ALOGE("%s::VIDIOC_G_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001232 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001241 ALOGE("%s::VIDIOC_S_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001242 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001250 ALOGE("%s::VIDIOC_G_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001251 return false;
1252 }
1253
1254 fmt.fmt.win.global_alpha = alpha & 0xFF;
1255 if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001256 ALOGE("%s::VIDIOC_S_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001257 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001271 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001272 return false;
1273 }
1274
1275 if (mFlagStreamOn == true) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001276 ALOGE("%s::mFlagStreamOn == true", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001277 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001292 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001293 return false;
1294 }
1295
1296 if (mFlagStreamOn == true) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001297 ALOGE("%s::mFlagStreamOn == true", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001298 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001307 ALOGE("%s::VIDIOC_G_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001308 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001317 ALOGE("%s::VIDIOC_S_FBUF failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001318 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001326 ALOGE("%s::VIDIOC_G_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001327 return false;
1328 }
1329
1330 fmt.fmt.win.chromakey = colorKey & 0xFFFFFF;
1331
1332 if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0)
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001333 ALOGE("%s::VIDIOC_S_FMT failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001334 }
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
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001343 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001344#endif
1345
1346 if (mFlagCreate == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001347 ALOGE("%s::Not yet created", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001348 return false;
1349 }
1350
1351 if (mFlagSetSrcParam == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001352 ALOGE("%s::mFlagSetSrcParam == false fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001353 return false;
1354 }
1355
1356 if (mFlagSetDstParam == false) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001357 ALOGE("%s::mFlagSetDstParam == false fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001358 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001371 ALOGE("%s::m_streamOn failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001372 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001377 ALOGE("%s::fimc_v4l2_dequeue[dst](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001378 return false;
1379 }
1380
1381 if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001382 ALOGE("%s::fimc_v4l2_dequeue[src](mNumOfBuf : %d) failed", __func__, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001383 return false;
1384 }
1385
1386 if (fimc_v4l2_queue(mFd, &(mSrcBuffer), V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, src_index, src_planes) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001387 ALOGE("%s::fimc_v4l2_queue[src](index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001388 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001392 ALOGE("%s::fimc_v4l2_queue[dst](index : %d) (mNumOfBuf : %d) failed", __func__, dst_index, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001393 return false;
1394 }
1395#else
1396 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001397 ALOGE("%s::fimc_v4l2_stream_on() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001398 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001404 ALOGE("%s::fimc_v4l2_queue(index : %d) (mNumOfBuf : %d) failed", __func__, 0, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001405 goto err;
1406 }
1407
1408 if (fimc_v4l2_dequeue(mFd, V4L2_BUF_TYPE_SRC, V4L2_MEMORY_TYPE_SRC, &src_index, src_planes) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001409 ALOGE("%s::fimc_v4l2_dequeue (mNumOfBuf : %d) failed", __func__, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001410 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001418 ALOGE("%s::fimc_v4l2_stream_off() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001419 return false;
1420 }
1421 }
1422#endif
1423
1424 return true;
1425}
1426
1427bool SecFimc::m_streamOn()
1428{
1429#ifdef DEBUG_LIB_FIMC
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001430 ALOGD("%s", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001431#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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001457 ALOGE("%s::fimc_v4l2_queue(index : %d) (mSrcBufNum : %d) failed", __func__, 0, 1);
codeworkx62f02ba2012-05-20 12:00:36 +02001458 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) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001464 ALOGE("%s::fimc_v4l2_queue(index : %d) (mDstBufNum : %d) failed", __func__, i, mNumOfBuf);
codeworkx62f02ba2012-05-20 12:00:36 +02001465 return false;
1466 }
1467 }
1468#endif
1469 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_SRC) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001470 ALOGE("%s::fimc_v4l2_stream_on() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001471 return false;
1472 }
1473
1474#ifdef BOARD_USE_V4L2
1475 if (fimc_v4l2_stream_on(mFd, V4L2_BUF_TYPE_DST) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +02001476 ALOGE("%s::fimc_v4l2_stream_on() failed", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001477 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}