blob: d210dfdab9fff4b7cffd630368c58ae205af467c [file] [log] [blame]
codeworkx62f02ba2012-05-20 12:00:36 +02001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Revision History:
19 * - 2011/03/11 : Rama, Meka(v.meka@samsung.com)
20 * Initial version
21 *
22 * - 2011/12/07 : Jeonghee, Kim(jhhhh.kim@samsung.com)
23 * Add V4L2_PIX_FMT_YUV420M V4L2_PIX_FMT_NV12M
24 *
25 */
26
27#include "SecHWCUtils.h"
codeworkx62f02ba2012-05-20 12:00:36 +020028#define V4L2_BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_OUTPUT
29#define V4L2_BUF_TYPE_CAPTURE V4L2_BUF_TYPE_VIDEO_CAPTURE
codeworkx62f02ba2012-05-20 12:00:36 +020030
31#define EXYNOS4_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
32
33//#define CHECK_FPS
34#ifdef CHECK_FPS
35#include <sys/time.h>
36#include <unistd.h>
espenfjo34f9d5d2012-12-01 18:52:36 +010037#define CHK_FRAME_CNT 57
codeworkx62f02ba2012-05-20 12:00:36 +020038
39void check_fps()
40{
41 static struct timeval tick, tick_old;
42 static int total = 0;
43 static int cnt = 0;
44 int FPS;
45 cnt++;
46 gettimeofday(&tick, NULL);
47 if (cnt > 10) {
48 if (tick.tv_sec > tick_old.tv_sec)
49 total += ((tick.tv_usec/1000) + (tick.tv_sec - tick_old.tv_sec)*1000 - (tick_old.tv_usec/1000));
50 else
51 total += ((tick.tv_usec - tick_old.tv_usec)/1000);
52
53 memcpy(&tick_old, &tick, sizeof(timeval));
54 if (cnt == (10 + CHK_FRAME_CNT)) {
55 FPS = 1000*CHK_FRAME_CNT/total;
espenfjo34f9d5d2012-12-01 18:52:36 +010056 ALOGE("[FPS]:%d\n", FPS);
codeworkx62f02ba2012-05-20 12:00:36 +020057 total = 0;
58 cnt = 10;
59 }
60 } else {
61 memcpy(&tick_old, &tick, sizeof(timeval));
62 total = 0;
63 }
64}
65#endif
66
67struct yuv_fmt_list yuv_list[] = {
68 { "V4L2_PIX_FMT_NV12", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12, 12, 2 },
69 { "V4L2_PIX_FMT_NV12T", "YUV420/2P/LSB_CBCR", V4L2_PIX_FMT_NV12T, 12, 2 },
70 { "V4L2_PIX_FMT_NV21", "YUV420/2P/LSB_CRCB", V4L2_PIX_FMT_NV21, 12, 2 },
71 { "V4L2_PIX_FMT_NV21X", "YUV420/2P/MSB_CBCR", V4L2_PIX_FMT_NV21X, 12, 2 },
72 { "V4L2_PIX_FMT_NV12X", "YUV420/2P/MSB_CRCB", V4L2_PIX_FMT_NV12X, 12, 2 },
73 { "V4L2_PIX_FMT_YUV420", "YUV420/3P", V4L2_PIX_FMT_YUV420, 12, 3 },
codeworkx62f02ba2012-05-20 12:00:36 +020074 { "V4L2_PIX_FMT_YUYV", "YUV422/1P/YCBYCR", V4L2_PIX_FMT_YUYV, 16, 1 },
75 { "V4L2_PIX_FMT_YVYU", "YUV422/1P/YCRYCB", V4L2_PIX_FMT_YVYU, 16, 1 },
76 { "V4L2_PIX_FMT_UYVY", "YUV422/1P/CBYCRY", V4L2_PIX_FMT_UYVY, 16, 1 },
77 { "V4L2_PIX_FMT_VYUY", "YUV422/1P/CRYCBY", V4L2_PIX_FMT_VYUY, 16, 1 },
78 { "V4L2_PIX_FMT_UV12", "YUV422/2P/LSB_CBCR", V4L2_PIX_FMT_NV16, 16, 2 },
79 { "V4L2_PIX_FMT_UV21", "YUV422/2P/LSB_CRCB", V4L2_PIX_FMT_NV61, 16, 2 },
80 { "V4L2_PIX_FMT_UV12X", "YUV422/2P/MSB_CBCR", V4L2_PIX_FMT_NV16X, 16, 2 },
81 { "V4L2_PIX_FMT_UV21X", "YUV422/2P/MSB_CRCB", V4L2_PIX_FMT_NV61X, 16, 2 },
82 { "V4L2_PIX_FMT_YUV422P", "YUV422/3P", V4L2_PIX_FMT_YUV422P, 16, 3 },
83};
84
85int window_open(struct hwc_win_info_t *win, int id)
86{
87 int fd = 0;
88 char name[64];
89 int vsync = 1;
90 int real_id = id;
91
92 char const * const device_template = "/dev/graphics/fb%u";
93 // window & FB maping
94 // fb0 -> win-id : 2
95 // fb1 -> win-id : 3
96 // fb2 -> win-id : 4
97 // fb3 -> win-id : 0
98 // fb4 -> win_id : 1
99 // it is pre assumed that ...win0 or win1 is used here..
100
101 switch (id) {
102 case 0:
codeworkx62f02ba2012-05-20 12:00:36 +0200103 real_id = 3;
codeworkx62f02ba2012-05-20 12:00:36 +0200104 break;
105 case 1:
codeworkx62f02ba2012-05-20 12:00:36 +0200106 real_id = 4;
codeworkx62f02ba2012-05-20 12:00:36 +0200107 break;
codeworkx39aefd02012-12-02 19:39:25 +0100108 case 2:
109 real_id = 0;
110 break;
111 case 3:
112 real_id = 1;
113 break;
114 case 4:
115 real_id = 2;
116 break;
codeworkx62f02ba2012-05-20 12:00:36 +0200117 default:
118 SEC_HWC_Log(HWC_LOG_ERROR, "%s::id(%d) is weird", __func__, id);
119 goto error;
120}
121
122// 0/10
123// snprintf(name, 64, device_template, id + 3);
124// 5/10
125// snprintf(name, 64, device_template, id + 0);
126// 0/10
127// snprintf(name, 64, device_template, id + 1);
128 snprintf(name, 64, device_template, real_id);
129
130 win->fd = open(name, O_RDWR);
131 if (win->fd <= 0) {
132 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Failed to open window device (%s) : %s",
133 __func__, strerror(errno), name);
134 goto error;
135 }
136
137#ifdef ENABLE_FIMD_VSYNC
138 if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) {
139 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
140 goto error;
141 }
142#endif
143
144 return 0;
145
146error:
147 if (0 < win->fd)
148 close(win->fd);
149 win->fd = 0;
150
151 return -1;
152}
153
154int window_close(struct hwc_win_info_t *win)
155{
156 int ret = 0;
157
158 if (0 < win->fd) {
159
codeworkx62f02ba2012-05-20 12:00:36 +0200160#ifdef ENABLE_FIMD_VSYNC
161 int vsync = 0;
162 if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0)
163 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
164#endif
165 ret = close(win->fd);
166 }
167 win->fd = 0;
168
169 return ret;
170}
171
172int window_set_pos(struct hwc_win_info_t *win)
173{
174 struct s3cfb_user_window window;
175
176 //before changing the screen configuration...powerdown the window
177 if (window_hide(win) != 0)
178 return -1;
179
180 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: x(%d), y(%d)",
181 __func__, win->rect_info.x, win->rect_info.y);
182
183 win->var_info.xres_virtual = (win->lcd_info.xres + 15) & ~ 15;
184 win->var_info.yres_virtual = win->lcd_info.yres * NUM_OF_WIN_BUF;
185 win->var_info.xres = win->rect_info.w;
186 win->var_info.yres = win->rect_info.h;
187
188 win->var_info.activate &= ~FB_ACTIVATE_MASK;
189 win->var_info.activate |= FB_ACTIVATE_FORCE;
190
191 if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) {
192 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPUT_VSCREENINFO(%d, %d) fail",
193 __func__, win->rect_info.w, win->rect_info.h);
194 return -1;
195 }
196
197 window.x = win->rect_info.x;
198 window.y = win->rect_info.y;
199
200 if (ioctl(win->fd, S3CFB_WIN_POSITION, &window) < 0) {
201 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_WIN_POSITION(%d, %d) fail",
202 __func__, window.x, window.y);
203 return -1;
204 }
205
206 return 0;
207}
208
209int window_get_info(struct hwc_win_info_t *win, int win_num)
210{
211 int temp_size = 0;
212
213 if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) {
214 SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_FSCREENINFO failed : %s",
215 strerror(errno));
216 goto error;
217 }
218
219 win->size = win->fix_info.line_length * win->var_info.yres;
220
codeworkx62f02ba2012-05-20 12:00:36 +0200221 for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
222 temp_size = win->size * j;
codeworkx62f02ba2012-05-20 12:00:36 +0200223 win->addr[j] = win->fix_info.smem_start + temp_size;
codeworkx62f02ba2012-05-20 12:00:36 +0200224 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::win-%d add[%d] %x ",
225 __func__, win_num, j, win->addr[j]);
226 }
227 return 0;
228
229error:
230 win->fix_info.smem_start = 0;
231
232 return -1;
233}
234
235int window_pan_display(struct hwc_win_info_t *win)
236{
237 struct fb_var_screeninfo *lcd_info = &(win->lcd_info);
238
239#ifdef ENABLE_FIMD_VSYNC
codeworkx62f02ba2012-05-20 12:00:36 +0200240 if (ioctl(win->fd, FBIO_WAITFORVSYNC, 0) < 0)
241 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)",
242 __func__, strerror(errno));
243#endif
codeworkx62f02ba2012-05-20 12:00:36 +0200244
245 lcd_info->yoffset = lcd_info->yres * win->buf_index;
246
247 if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) {
248 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)",
249 __func__,
250 lcd_info->yres,
251 win->buf_index, lcd_info->yres_virtual,
252 strerror(errno));
253 return -1;
254 }
255 return 0;
256}
257
258int window_show(struct hwc_win_info_t *win)
259{
260 if (win->power_state == 0) {
261 if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
262 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
263 __func__, win->fd, strerror(errno));
264 return -1;
265 }
266 win->power_state = 1;
267 }
268 return 0;
269}
270
271int window_hide(struct hwc_win_info_t *win)
272{
273 if (win->power_state == 1) {
274 if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
275 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
276 __func__, win->fd, strerror(errno));
277 return -1;
278 }
279 win->power_state = 0;
280 }
281 return 0;
282}
283
codeworkx39aefd02012-12-02 19:39:25 +0100284int window_get_global_lcd_info(struct hwc_context_t *ctx)
codeworkx62f02ba2012-05-20 12:00:36 +0200285{
codeworkx39aefd02012-12-02 19:39:25 +0100286 if (ioctl(ctx->global_lcd_win.fd, FBIOGET_VSCREENINFO, &ctx->lcd_info) < 0) {
codeworkx62f02ba2012-05-20 12:00:36 +0200287 SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_VSCREENINFO failed : %s",
288 strerror(errno));
289 return -1;
290 }
291
codeworkx39aefd02012-12-02 19:39:25 +0100292 if (ctx->lcd_info.xres == 0) {
293 SEC_HWC_Log(HWC_LOG_ERROR, "ATTENTION: XRES IS 0");
294 }
295
296 if (ctx->lcd_info.yres == 0) {
297 SEC_HWC_Log(HWC_LOG_ERROR, "ATTENTION: YRES IS 0");
298 }
299
300 if (ctx->lcd_info.bits_per_pixel == 0) {
301 SEC_HWC_Log(HWC_LOG_ERROR, "ATTENTION: BPP IS 0");
302 }
303
codeworkx62f02ba2012-05-20 12:00:36 +0200304 return 0;
305}
306
307int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src)
308{
309 struct v4l2_format fmt;
310 struct v4l2_cropcap cropcap;
311 struct v4l2_crop crop;
312 struct v4l2_requestbuffers req;
313
codeworkx62f02ba2012-05-20 12:00:36 +0200314 fmt.fmt.pix.width = src->full_width;
315 fmt.fmt.pix.height = src->full_height;
316 fmt.fmt.pix.pixelformat = src->color_space;
317 fmt.fmt.pix.field = V4L2_FIELD_NONE;
codeworkx62f02ba2012-05-20 12:00:36 +0200318 fmt.type = V4L2_BUF_TYPE_OUTPUT;
319
320 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
321 SEC_HWC_Log(HWC_LOG_ERROR, "%s::VIDIOC_S_FMT failed : errno=%d (%s)"
322 " : fd=%d\n", __func__, errno, strerror(errno), fd);
323 return -1;
324 }
325
326 /* crop input size */
327 crop.type = V4L2_BUF_TYPE_OUTPUT;
328 crop.c.width = src->width;
329 crop.c.height = src->height;
codeworkx62f02ba2012-05-20 12:00:36 +0200330 if (0x50 <= hw_ver) {
331 crop.c.left = src->start_x;
332 crop.c.top = src->start_y;
333 } else {
334 crop.c.left = 0;
335 crop.c.top = 0;
336 }
337
codeworkx62f02ba2012-05-20 12:00:36 +0200338 if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
339 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP :"
340 "crop.c.left : (%d), crop.c.top : (%d), crop.c.width : (%d), crop.c.height : (%d)",
341 __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height);
342 return -1;
343 }
344
345 /* input buffer type */
346 req.count = 1;
347 req.memory = V4L2_MEMORY_USERPTR;
348 req.type = V4L2_BUF_TYPE_OUTPUT;
349
350 if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
351 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS", __func__);
352 return -1;
353 }
354
355 return 0;
356}
357
358int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst,
359 int rotation, int hflip, int vflip, unsigned int addr)
360{
361 struct v4l2_format sFormat;
362 struct v4l2_control vc;
363 struct v4l2_framebuffer fbuf;
codeworkx62f02ba2012-05-20 12:00:36 +0200364 int ret;
365
codeworkx62f02ba2012-05-20 12:00:36 +0200366 /* set rotation configuration */
codeworkx62f02ba2012-05-20 12:00:36 +0200367 vc.id = V4L2_CID_ROTATION;
codeworkx62f02ba2012-05-20 12:00:36 +0200368 vc.value = rotation;
369
370 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
371 if (ret < 0) {
372 SEC_HWC_Log(HWC_LOG_ERROR,
373 "%s::Error in video VIDIOC_S_CTRL - rotation (%d)"
374 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
375 return -1;
376 }
377
378 vc.id = V4L2_CID_HFLIP;
379 vc.value = hflip;
380
381 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
382 if (ret < 0) {
383 SEC_HWC_Log(HWC_LOG_ERROR,
384 "%s::Error in video VIDIOC_S_CTRL - hflip (%d)"
385 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
386 return -1;
387 }
388
389 vc.id = V4L2_CID_VFLIP;
390 vc.value = vflip;
391
392 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
393 if (ret < 0) {
394 SEC_HWC_Log(HWC_LOG_ERROR,
395 "%s::Error in video VIDIOC_S_CTRL - vflip (%d)"
396 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
397 return -1;
398 }
399
codeworkx62f02ba2012-05-20 12:00:36 +0200400 /* set size, format & address for destination image (DMA-OUTPUT) */
401 ret = ioctl(fd, VIDIOC_G_FBUF, &fbuf);
402 if (ret < 0) {
403 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FBUF (%d)", __func__, ret);
404 return -1;
405 }
406
407 fbuf.base = (void *)addr;
408 fbuf.fmt.width = dst->full_width;
409 fbuf.fmt.height = dst->full_height;
410 fbuf.fmt.pixelformat = dst->color_space;
411
412 ret = ioctl(fd, VIDIOC_S_FBUF, &fbuf);
413 if (ret < 0) {
414 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FBUF (%d)", __func__, ret);
415 return -1;
416 }
417
418 /* set destination window */
419 sFormat.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
420 sFormat.fmt.win.w.left = dst->start_x;
421 sFormat.fmt.win.w.top = dst->start_y;
422 sFormat.fmt.win.w.width = dst->width;
423 sFormat.fmt.win.w.height = dst->height;
424
425 ret = ioctl(fd, VIDIOC_S_FMT, &sFormat);
426 if (ret < 0) {
427 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret);
428 return -1;
429 }
codeworkx62f02ba2012-05-20 12:00:36 +0200430
431 return 0;
432}
433
434int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
435{
436 if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) {
437 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMON\n");
438 return -1;
439 }
440
441 return 0;
442}
443
444int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type, int index)
445{
codeworkx62f02ba2012-05-20 12:00:36 +0200446 struct v4l2_buffer buf;
447 int ret;
448
codeworkx62f02ba2012-05-20 12:00:36 +0200449 buf.length = 0;
450 buf.m.userptr = (unsigned long)fimc_buf;
codeworkx62f02ba2012-05-20 12:00:36 +0200451 buf.memory = V4L2_MEMORY_USERPTR;
452 buf.index = index;
453 buf.type = type;
454
codeworkx62f02ba2012-05-20 12:00:36 +0200455 ret = ioctl(fd, VIDIOC_QBUF, &buf);
456 if (0 > ret) {
457 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_QBUF : (%d)", ret);
458 return -1;
459 }
460
461 return 0;
462}
463
464int fimc_v4l2_dequeue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type)
465{
466 struct v4l2_buffer buf;
codeworkx62f02ba2012-05-20 12:00:36 +0200467
codeworkx62f02ba2012-05-20 12:00:36 +0200468 buf.memory = V4L2_MEMORY_USERPTR;
469 buf.type = type;
470
471 if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) {
472 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_DQBUF\n");
473 return -1;
474 }
475
476 return buf.index;
477}
478
479int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
480{
481 if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) {
482 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMOFF\n");
483 return -1;
484 }
485
486 return 0;
487}
488
489int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type)
490{
491 struct v4l2_requestbuffers req;
492
493 req.count = 0;
494 req.memory = V4L2_MEMORY_USERPTR;
495 req.type = type;
496
497 if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
498 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_REQBUFS");
499 }
500
501 return 0;
502}
503
504int fimc_v4l2_S_ctrl(int fd)
505{
506 struct v4l2_control vc;
507
508 vc.id = V4L2_CID_CACHEABLE;
509 vc.value = 1;
510
511 if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
512 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_S_CTRL");
513 return -1;
514 }
515
516 return 0;
517}
518
519int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_src_buf, struct fimc_buf *fimc_dst_buf)
520{
521#ifdef CHECK_FPS
522 check_fps();
523#endif
524
codeworkx62f02ba2012-05-20 12:00:36 +0200525 if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
526 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()");
527 return -5;
528 }
529
530 if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) {
531 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()");
532 goto STREAM_OFF;
533 }
codeworkx62f02ba2012-05-20 12:00:36 +0200534 if (fimc_v4l2_dequeue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT) < 0) {
535 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_dequeue()");
536 return -6;
537 }
codeworkx62f02ba2012-05-20 12:00:36 +0200538STREAM_OFF:
539 if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
540 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_off()");
541 return -8;
542 }
codeworkx62f02ba2012-05-20 12:00:36 +0200543 if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
544 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_clr_buf()");
545 return -10;
546 }
codeworkx62f02ba2012-05-20 12:00:36 +0200547 return 0;
548}
549
550static int memcpy_rect(void *dst, void *src, int fullW, int fullH, int realW, int realH, int format)
551{
552 unsigned char *srcCb, *srcCr;
553 unsigned char *dstCb, *dstCr;
554 unsigned char *srcY, *dstY;
555 int srcCbOffset, srcCrOffset;
556 int dstCbOffset, dstFrameOffset, dstCrOffset;
557 int cbFullW, cbRealW, cbFullH, cbRealH;
558 int ySrcFW, ySrcFH, ySrcRW, ySrcRH;
559 int planes;
560 int i;
561
562 SEC_HWC_Log(HWC_LOG_DEBUG,
563 "++memcpy_rect()::"
564 "dst(0x%x),src(0x%x),f.w(%d),f.h(%d),r.w(%d),r.h(%d),format(0x%x)",
565 (unsigned int)dst, (unsigned int)src, fullW, fullH, realW, realH, format);
566
567// Set dst Y, Cb, Cr address for FIMC
568 {
569 cbFullW = fullW >> 1;
570 cbRealW = realW >> 1;
571 cbFullH = fullH >> 1;
572 cbRealH = realH >> 1;
573 dstFrameOffset = fullW * fullH;
574 dstCrOffset = cbFullW * cbFullH;
575 dstY = (unsigned char *)dst;
576 dstCb = (unsigned char *)dst + dstFrameOffset;
577 dstCr = (unsigned char *)dstCb + dstCrOffset;
578 }
579
580// Get src Y, Cb, Cr address for source buffer.
581// Each address is aligned by 16's multiple for GPU both width and height.
582 {
583 ySrcFW = fullW;
584 ySrcFH = fullH;
585 ySrcRW = realW;
586 ySrcRH = realH;
587 srcCbOffset = EXYNOS4_ALIGN(ySrcRW,16)* EXYNOS4_ALIGN(ySrcRH,16);
588 srcCrOffset = EXYNOS4_ALIGN(cbRealW,16)* EXYNOS4_ALIGN(cbRealH,16);
589 srcY = (unsigned char *)src;
590 srcCb = (unsigned char *)src + srcCbOffset;
591 srcCr = (unsigned char *)srcCb + srcCrOffset;
592 }
593 SEC_HWC_Log(HWC_LOG_DEBUG,
594 "--memcpy_rect()::\n"
595 "dstY(0x%x),dstCb(0x%x),dstCr(0x%x) \n"
596 "srcY(0x%x),srcCb(0x%x),srcCr(0x%x) \n"
597 "cbRealW(%d),cbRealH(%d)",
598 (unsigned int)dstY,(unsigned int)dstCb,(unsigned int)dstCr,
599 (unsigned int)srcY,(unsigned int)srcCb,(unsigned int)srcCr,
600 cbRealW, cbRealH);
601
602 if (format == HAL_PIXEL_FORMAT_YV12) { //YV12(Y,Cr,Cv)
603 planes = 3;
604//This is code for VE, deleted temporory by SSONG 2011.09.22
605// This will be enabled later.
606/*
607 //as defined in hardware.h, cb & cr full_width should be aligned to 16. ALIGN(y_stride/2, 16).
608 ////Alignment is hard coded to 16.
609 ////for example...check frameworks/media/libvideoeditor/lvpp/VideoEditorTools.cpp file for UV stride cal
610 cbSrcFW = (cbSrcFW + 15) & (~15);
611 srcCbOffset = ySrcFW * fullH;
612 srcCrOffset = srcCbOffset + ((cbSrcFW * fullH) >> 1);
613 srcY = (unsigned char *)src;
614 srcCb = (unsigned char *)src + srcCbOffset;
615 srcCr = (unsigned char *)src + srcCrOffset;
616*/
617 } else if ((format == HAL_PIXEL_FORMAT_YCbCr_420_P)) {
618 planes = 3;
619 } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
620 planes = 2;
621 } else {
622 SEC_HWC_Log(HWC_LOG_ERROR, "use default memcpy instead of memcpy_rect");
623 return -1;
624 }
625//#define CHECK_PERF
626#ifdef CHECK_PERF
627 struct timeval start, end;
628 gettimeofday(&start, NULL);
629#endif
630 for (i = 0; i < realH; i++)
631 memcpy(dstY + fullW * i, srcY + ySrcFW * i, ySrcRW);
632 if (planes == 2) {
633 for (i = 0; i < cbRealH; i++)
634 memcpy(dstCb + ySrcFW * i, srcCb + ySrcFW * i, ySrcRW);
635 } else if (planes == 3) {
636 for (i = 0; i < cbRealH; i++)
637 memcpy(dstCb + cbFullW * i, srcCb + cbFullW * i, cbRealW);
638 for (i = 0; i < cbRealH; i++)
639 memcpy(dstCr + cbFullW * i, srcCr + cbFullW * i, cbRealW);
640 }
641#ifdef CHECK_PERF
642 gettimeofday(&end, NULL);
643 SEC_HWC_Log(HWC_LOG_ERROR, "[COPY]=%d,",(end.tv_sec - start.tv_sec)*1000+(end.tv_usec - start.tv_usec)/1000);
644#endif
645
646 return 0;
647}
648
649/*****************************************************************************/
650static int get_src_phys_addr(struct hwc_context_t *ctx,
651 sec_img *src_img, sec_rect *src_rect)
652{
653 s5p_fimc_t *fimc = &ctx->fimc;
codeworkx62f02ba2012-05-20 12:00:36 +0200654
655 unsigned int src_virt_addr = 0;
656 unsigned int src_phys_addr = 0;
657 unsigned int src_frame_size = 0;
658
codeworkx62f02ba2012-05-20 12:00:36 +0200659 ADDRS * addr;
660
661 // error check routine
662 if (0 == src_img->base && !(src_img->usage & GRALLOC_USAGE_HW_FIMC1)) {
663 SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src image base\n", __func__);
664 return 0;
665 }
666
667 switch (src_img->mem_type) {
668 case HWC_PHYS_MEM_TYPE:
669 src_phys_addr = src_img->base + src_img->offset;
670 break;
671
672 case HWC_VIRT_MEM_TYPE:
673 case HWC_UNKNOWN_MEM_TYPE:
674 switch (src_img->format) {
675 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
676 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
677 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
678 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
679 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
680 addr = (ADDRS *)(src_img->base);
681 fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
682 fimc->params.src.buf_addr_phy_cb = addr->addr_cbcr;
683
684 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
685 if (0 == src_phys_addr) {
686 SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
687 "(format=CUSTOM_YCbCr/YCrCb_420_SP Y-addr=0x%x "
688 "CbCr-Addr=0x%x)",
689 __func__, fimc->params.src.buf_addr_phy_rgb_y,
690 fimc->params.src.buf_addr_phy_cb);
691 return 0;
692 }
693 break;
694 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
695 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
696 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
697 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
698 addr = (ADDRS *)(src_img->base + src_img->offset);
699 fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
700 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
701 if (0 == src_phys_addr) {
702 SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
703 "(format=CUSTOM_YCbCr/CbYCrY_422_I Y-addr=0x%x)",
704 __func__, fimc->params.src.buf_addr_phy_rgb_y);
705 return 0;
706 }
707 break;
708 default:
codeworkx62f02ba2012-05-20 12:00:36 +0200709 if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
710 fimc->params.src.buf_addr_phy_rgb_y = src_img->paddr;
711 fimc->params.src.buf_addr_phy_cb = src_img->paddr + src_img->uoffset;
712 fimc->params.src.buf_addr_phy_cr = src_img->paddr + src_img->uoffset + src_img->voffset;
713 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
codeworkx62f02ba2012-05-20 12:00:36 +0200714 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100715 SEC_HWC_Log(HWC_LOG_ERROR, "%s::\nformat = 0x%x : Not "
716 "GRALLOC_USAGE_HW_FIMC1 can not supported\n",
717 __func__, src_img->format);
codeworkx62f02ba2012-05-20 12:00:36 +0200718 }
codeworkx62f02ba2012-05-20 12:00:36 +0200719 break;
720 }
721 }
722
723 return src_phys_addr;
724}
725
codeworkx62f02ba2012-05-20 12:00:36 +0200726static inline int rotateValueHAL2PP(unsigned char transform)
727{
728 int rotate_flag = transform & 0x7;
729
730 switch (rotate_flag) {
731 case HAL_TRANSFORM_ROT_90: return 90;
732 case HAL_TRANSFORM_ROT_180: return 180;
733 case HAL_TRANSFORM_ROT_270: return 270;
734 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: return 90;
735 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: return 90;
736 case HAL_TRANSFORM_FLIP_H: return 0;
737 case HAL_TRANSFORM_FLIP_V: return 0;
738 }
739 return 0;
740}
741
742static inline int hflipValueHAL2PP(unsigned char transform)
743{
744 int flip_flag = transform & 0x7;
745 switch (flip_flag) {
746 case HAL_TRANSFORM_FLIP_H:
747 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
748 return 1;
749 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
750 case HAL_TRANSFORM_ROT_90:
751 case HAL_TRANSFORM_ROT_180:
752 case HAL_TRANSFORM_ROT_270:
753 case HAL_TRANSFORM_FLIP_V:
754 break;
755 }
756 return 0;
757}
758
759static inline int vflipValueHAL2PP(unsigned char transform)
760{
761 int flip_flag = transform & 0x7;
762 switch (flip_flag) {
763 case HAL_TRANSFORM_FLIP_V:
764 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
765 return 1;
766 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
767 case HAL_TRANSFORM_ROT_90:
768 case HAL_TRANSFORM_ROT_180:
769 case HAL_TRANSFORM_ROT_270:
770 case HAL_TRANSFORM_FLIP_H:
771 break;
772 }
773 return 0;
774}
775
776static inline int multipleOf2(int number)
777{
778 if (number % 2 == 1)
779 return (number - 1);
780 else
781 return number;
782}
783
784static inline int multipleOf4(int number)
785{
786 int remain_number = number % 4;
787
788 if (remain_number != 0)
789 return (number - remain_number);
790 else
791 return number;
792}
793
794static inline int multipleOf8(int number)
795{
796 int remain_number = number % 8;
797
798 if (remain_number != 0)
799 return (number - remain_number);
800 else
801 return number;
802}
803
804static inline int multipleOf16(int number)
805{
806 int remain_number = number % 16;
807
808 if (remain_number != 0)
809 return (number - remain_number);
810 else
811 return number;
812}
813
814static inline int widthOfPP(unsigned int ver, int pp_color_format, int number)
815{
codeworkx62f02ba2012-05-20 12:00:36 +0200816 if (0x50 <= ver) {
codeworkx62f02ba2012-05-20 12:00:36 +0200817 switch (pp_color_format) {
818 /* 422 1/2/3 plane */
819 case V4L2_PIX_FMT_YUYV:
820 case V4L2_PIX_FMT_UYVY:
821 case V4L2_PIX_FMT_NV61:
822 case V4L2_PIX_FMT_NV16:
823 case V4L2_PIX_FMT_YUV422P:
824
825 /* 420 2/3 plane */
826 case V4L2_PIX_FMT_NV21:
827 case V4L2_PIX_FMT_NV12:
828 case V4L2_PIX_FMT_NV12T:
829 case V4L2_PIX_FMT_YUV420:
830 return multipleOf2(number);
831
832 default :
833 return number;
834 }
835 } else {
836 switch (pp_color_format) {
837 case V4L2_PIX_FMT_RGB565:
838 return multipleOf8(number);
839
840 case V4L2_PIX_FMT_RGB32:
841 return multipleOf4(number);
842
843 case V4L2_PIX_FMT_YUYV:
844 case V4L2_PIX_FMT_UYVY:
845 return multipleOf4(number);
846
847 case V4L2_PIX_FMT_NV61:
848 case V4L2_PIX_FMT_NV16:
849 return multipleOf8(number);
850
851 case V4L2_PIX_FMT_YUV422P:
852 return multipleOf16(number);
853
854 case V4L2_PIX_FMT_NV21:
855 case V4L2_PIX_FMT_NV12:
856 case V4L2_PIX_FMT_NV12T:
857 return multipleOf8(number);
858
859 case V4L2_PIX_FMT_YUV420:
860 return multipleOf16(number);
861
862 default :
863 return number;
864 }
865 }
866 return number;
867}
868
869static inline int heightOfPP(int pp_color_format, int number)
870{
871 switch (pp_color_format) {
872 case V4L2_PIX_FMT_NV21:
873 case V4L2_PIX_FMT_NV12:
874 case V4L2_PIX_FMT_NV12T:
875 case V4L2_PIX_FMT_YUV420:
876 return multipleOf2(number);
877
878 default :
879 return number;
880 break;
881 }
882 return number;
883}
884
885static unsigned int get_yuv_bpp(unsigned int fmt)
886{
887 int i, sel = -1;
888
889 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
890 if (yuv_list[i].fmt == fmt) {
891 sel = i;
892 break;
893 }
894 }
895
896 if (sel == -1)
897 return sel;
898 else
899 return yuv_list[sel].bpp;
900}
901
902static unsigned int get_yuv_planes(unsigned int fmt)
903{
904 int i, sel = -1;
905
906 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
907 if (yuv_list[i].fmt == fmt) {
908 sel = i;
909 break;
910 }
911 }
912
913 if (sel == -1)
914 return sel;
915 else
916 return yuv_list[sel].planes;
917}
918
espenfjo34f9d5d2012-12-01 18:52:36 +0100919static int runFimcCore(struct hwc_context_t *ctx,
codeworkx62f02ba2012-05-20 12:00:36 +0200920 unsigned int src_phys_addr, sec_img *src_img, sec_rect *src_rect,
921 uint32_t src_color_space,
922 unsigned int dst_phys_addr, sec_img *dst_img, sec_rect *dst_rect,
923 uint32_t dst_color_space, int transform)
924{
925 s5p_fimc_t * fimc = &ctx->fimc;
926 s5p_fimc_params_t * params = &(fimc->params);
927
928 struct fimc_buf fimc_src_buf;
929 int src_bpp, src_planes;
930
codeworkx62f02ba2012-05-20 12:00:36 +0200931 unsigned int frame_size = 0;
932
933 bool src_cbcr_order = true;
934 int rotate_value = rotateValueHAL2PP(transform);
espenfjo34f9d5d2012-12-01 18:52:36 +0100935 int hflip = 0;
936 int vflip = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200937
938 /* 1. param(fimc config)->src information
939 * - src_img,src_rect => s_fw,s_fh,s_w,s_h,s_x,s_y
940 */
941 params->src.full_width = src_img->f_w;
942 params->src.full_height = src_img->f_h;
943 params->src.width = src_rect->w;
944 params->src.height = src_rect->h;
945 params->src.start_x = src_rect->x;
946 params->src.start_y = src_rect->y;
947 params->src.color_space = src_color_space;
948 params->src.buf_addr_phy_rgb_y = src_phys_addr;
949
codeworkx62f02ba2012-05-20 12:00:36 +0200950 /* check src minimum */
951 if (src_rect->w < 16 || src_rect->h < 8) {
952 SEC_HWC_Log(HWC_LOG_ERROR,
953 "%s src size is not supported by fimc : f_w=%d f_h=%d "
954 "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
955 params->src.full_width, params->src.full_height,
956 params->src.start_x, params->src.start_y,
957 params->src.width, params->src.height,
958 src_rect->w, src_rect->h,
959 params->src.color_space);
960 return -1;
961 }
962
codeworkx62f02ba2012-05-20 12:00:36 +0200963 /* 2. param(fimc config)->dst information
964 * - dst_img,dst_rect,rot => d_fw,d_fh,d_w,d_h,d_x,d_y
965 */
966 switch (rotate_value) {
967 case 0:
espenfjo34f9d5d2012-12-01 18:52:36 +0100968 hflip = hflipValueHAL2PP(transform);
969 vflip = vflipValueHAL2PP(transform);
codeworkx62f02ba2012-05-20 12:00:36 +0200970 params->dst.full_width = dst_img->f_w;
971 params->dst.full_height = dst_img->f_h;
972
973 params->dst.start_x = dst_rect->x;
974 params->dst.start_y = dst_rect->y;
975
976 params->dst.width =
977 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
978 params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
979 break;
980 case 90:
espenfjo34f9d5d2012-12-01 18:52:36 +0100981 hflip = vflipValueHAL2PP(transform);
982 vflip = hflipValueHAL2PP(transform);
codeworkx62f02ba2012-05-20 12:00:36 +0200983 params->dst.full_width = dst_img->f_h;
984 params->dst.full_height = dst_img->f_w;
985
986 params->dst.start_x = dst_rect->y;
987 params->dst.start_y = dst_img->f_w - (dst_rect->x + dst_rect->w);
988
989 params->dst.width =
990 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
991 params->dst.height =
992 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
993
994 if (0x50 > fimc->hw_ver)
995 params->dst.start_y += (dst_rect->w - params->dst.height);
996 break;
997 case 180:
998 params->dst.full_width = dst_img->f_w;
999 params->dst.full_height = dst_img->f_h;
1000
1001 params->dst.start_x = dst_img->f_w - (dst_rect->x + dst_rect->w);
1002 params->dst.start_y = dst_img->f_h - (dst_rect->y + dst_rect->h);
1003
1004 params->dst.width =
1005 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
1006 params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
1007 break;
1008 case 270:
1009 params->dst.full_width = dst_img->f_h;
1010 params->dst.full_height = dst_img->f_w;
1011
1012 params->dst.start_x = dst_img->f_h - (dst_rect->y + dst_rect->h);
1013 params->dst.start_y = dst_rect->x;
1014
1015 params->dst.width =
1016 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
1017 params->dst.height =
1018 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
1019
1020 if (0x50 > fimc->hw_ver)
1021 params->dst.start_y += (dst_rect->w - params->dst.height);
1022 break;
1023 }
1024 params->dst.color_space = dst_color_space;
codeworkx62f02ba2012-05-20 12:00:36 +02001025
1026 SEC_HWC_Log(HWC_LOG_DEBUG,
espenfjo34f9d5d2012-12-01 18:52:36 +01001027 "runFimcCore()::"
codeworkx62f02ba2012-05-20 12:00:36 +02001028 "SRC f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)=>"
1029 "DST f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)",
1030 params->src.full_width, params->src.full_height,
1031 params->src.start_x, params->src.start_y,
1032 params->src.width, params->src.height,
1033 params->dst.full_width, params->dst.full_height,
1034 params->dst.start_x, params->dst.start_y,
1035 params->dst.width, params->dst.height);
1036
1037 /* check dst minimum */
1038 if (dst_rect->w < 8 || dst_rect->h < 4) {
1039 SEC_HWC_Log(HWC_LOG_ERROR,
1040 "%s dst size is not supported by fimc : f_w=%d f_h=%d "
1041 "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
1042 params->dst.full_width, params->dst.full_height,
1043 params->dst.start_x, params->dst.start_y,
1044 params->dst.width, params->dst.height,
1045 dst_rect->w, dst_rect->h, params->dst.color_space);
1046 return -1;
1047 }
1048 /* check scaling limit
1049 * the scaling limie must not be more than MAX_RESIZING_RATIO_LIMIT
1050 */
1051 if (((src_rect->w > dst_rect->w) &&
1052 ((src_rect->w / dst_rect->w) > MAX_RESIZING_RATIO_LIMIT)) ||
1053 ((dst_rect->w > src_rect->w) &&
1054 ((dst_rect->w / src_rect->w) > MAX_RESIZING_RATIO_LIMIT))) {
1055 SEC_HWC_Log(HWC_LOG_ERROR,
1056 "%s over scaling limit : src.w=%d dst.w=%d (limit=%d)",
1057 __func__, src_rect->w, dst_rect->w, MAX_RESIZING_RATIO_LIMIT);
1058 return -1;
1059 }
1060
1061 /* 3. Set configuration related to destination (DMA-OUT)
1062 * - set input format & size
1063 * - crop input size
1064 * - set input buffer
1065 * - set buffer type (V4L2_MEMORY_USERPTR)
1066 */
codeworkx62f02ba2012-05-20 12:00:36 +02001067
1068 if (fimc_v4l2_set_dst(fimc->dev_fd, &params->dst, rotate_value, hflip, vflip, dst_phys_addr) < 0) {
1069 SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_dst is failed\n");
1070 return -1;
1071 }
1072
1073 /* 4. Set configuration related to source (DMA-INPUT)
1074 * - set input format & size
1075 * - crop input size
1076 * - set input buffer
1077 * - set buffer type (V4L2_MEMORY_USERPTR)
1078 */
codeworkx62f02ba2012-05-20 12:00:36 +02001079 if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, &params->src) < 0) {
1080 SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n");
1081 return -1;
1082 }
codeworkx62f02ba2012-05-20 12:00:36 +02001083
1084 /* 5. Set input dma address (Y/RGB, Cb, Cr)
1085 * - zero copy : mfc, camera
codeworkx62f02ba2012-05-20 12:00:36 +02001086 */
1087 switch (src_img->format) {
1088 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
1089 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
1090 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
1091 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
1092 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
1093 /* for video contents zero copy case */
1094 fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
1095 fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
1096 break;
1097
1098 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
1099 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
1100 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
1101 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
1102 case HAL_PIXEL_FORMAT_RGB_565:
1103 case HAL_PIXEL_FORMAT_YV12:
1104 default:
espenfjo34f9d5d2012-12-01 18:52:36 +01001105 if (src_img->format == HAL_PIXEL_FORMAT_YV12){
codeworkx62f02ba2012-05-20 12:00:36 +02001106 src_cbcr_order = false;
codeworkx62f02ba2012-05-20 12:00:36 +02001107 }
codeworkx62f02ba2012-05-20 12:00:36 +02001108
1109 if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
1110 fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
1111 if (src_cbcr_order == true) {
1112 fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
1113 fimc_src_buf.base[2] = params->src.buf_addr_phy_cr;
1114 }
1115 else {
1116 fimc_src_buf.base[2] = params->src.buf_addr_phy_cb;
1117 fimc_src_buf.base[1] = params->src.buf_addr_phy_cr;
1118 }
1119 SEC_HWC_Log(HWC_LOG_DEBUG,
1120 "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n",
1121 fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]);
1122 break;
1123 }
codeworkx62f02ba2012-05-20 12:00:36 +02001124 }
1125
1126 /* 6. Run FIMC
1127 * - stream on => queue => dequeue => stream off => clear buf
1128 */
codeworkx62f02ba2012-05-20 12:00:36 +02001129 if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, NULL) < 0) {
espenfjo34f9d5d2012-12-01 18:52:36 +01001130 ALOGE("fimcrun fail");
codeworkx62f02ba2012-05-20 12:00:36 +02001131 fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT);
1132 return -1;
1133 }
codeworkx62f02ba2012-05-20 12:00:36 +02001134
1135 return 0;
1136}
1137
codeworkx62f02ba2012-05-20 12:00:36 +02001138int createFimc(s5p_fimc_t *fimc)
1139{
1140 struct v4l2_capability cap;
1141 struct v4l2_format fmt;
1142 struct v4l2_control vc;
1143
1144 // open device file
1145 if (fimc->dev_fd <= 0)
1146 fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR);
1147
1148 if (fimc->dev_fd <= 0) {
1149 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Post processor open error (%d)",
1150 __func__, errno);
1151 goto err;
1152 }
1153
1154 // check capability
1155 if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) {
1156 SEC_HWC_Log(HWC_LOG_ERROR, "VIDIOC_QUERYCAP failed");
1157 goto err;
1158 }
1159
1160 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
1161 SEC_HWC_Log(HWC_LOG_ERROR, "%d has no streaming support", fimc->dev_fd);
1162 goto err;
1163 }
1164
1165 if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
1166 SEC_HWC_Log(HWC_LOG_ERROR, "%d is no video output", fimc->dev_fd);
1167 goto err;
1168 }
1169
1170 /*
1171 * malloc fimc_outinfo structure
1172 */
1173 fmt.type = V4L2_BUF_TYPE_OUTPUT;
1174 if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) {
1175 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FMT", __func__);
1176 goto err;
1177 }
1178
codeworkx62f02ba2012-05-20 12:00:36 +02001179 vc.id = V4L2_CID_FIMC_VERSION;
1180 vc.value = 0;
1181
1182 if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) {
1183 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_CTRL", __func__);
1184 goto err;
1185 }
1186 fimc->hw_ver = vc.value;
codeworkx62f02ba2012-05-20 12:00:36 +02001187
1188 return 0;
1189
1190err:
1191 if (0 < fimc->dev_fd)
1192 close(fimc->dev_fd);
1193 fimc->dev_fd =0;
1194
1195 return -1;
1196}
1197
1198int destroyFimc(s5p_fimc_t *fimc)
1199{
1200 if (fimc->out_buf.virt_addr != NULL) {
1201 fimc->out_buf.virt_addr = NULL;
1202 fimc->out_buf.length = 0;
1203 }
1204
1205 // close
1206 if (0 < fimc->dev_fd)
1207 close(fimc->dev_fd);
1208 fimc->dev_fd = 0;
1209
1210 return 0;
1211}
1212
1213int runFimc(struct hwc_context_t *ctx,
1214 struct sec_img *src_img, struct sec_rect *src_rect,
1215 struct sec_img *dst_img, struct sec_rect *dst_rect,
1216 uint32_t transform)
1217{
1218 s5p_fimc_t * fimc = &ctx->fimc;
1219
1220 unsigned int src_phys_addr = 0;
1221 unsigned int dst_phys_addr = 0;
1222 int rotate_value = 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001223 int32_t src_color_space;
1224 int32_t dst_color_space;
1225
1226 /* 1. source address and size */
1227 src_phys_addr = get_src_phys_addr(ctx, src_img, src_rect);
1228 if (0 == src_phys_addr)
1229 return -1;
1230
1231 /* 2. destination address and size */
espenfjo34f9d5d2012-12-01 18:52:36 +01001232 dst_phys_addr = dst_img->base;
codeworkx62f02ba2012-05-20 12:00:36 +02001233 if (0 == dst_phys_addr)
1234 return -2;
1235
1236 /* 3. check whether fimc supports the src format */
1237 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1238 if (0 > src_color_space)
1239 return -3;
1240 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1241 if (0 > dst_color_space)
1242 return -4;
1243
1244 /* 4. FIMC: src_rect of src_img => dst_rect of dst_img */
espenfjo34f9d5d2012-12-01 18:52:36 +01001245 if (runFimcCore(ctx, src_phys_addr, src_img, src_rect,
codeworkx62f02ba2012-05-20 12:00:36 +02001246 (uint32_t)src_color_space, dst_phys_addr, dst_img, dst_rect,
1247 (uint32_t)dst_color_space, transform) < 0)
1248 return -5;
1249
codeworkx62f02ba2012-05-20 12:00:36 +02001250 return 0;
1251}
1252
espenfjo34f9d5d2012-12-01 18:52:36 +01001253int check_yuv_format(unsigned int color_format) {
1254 switch (color_format) {
1255 case HAL_PIXEL_FORMAT_YV12:
1256 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1257 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1258 case HAL_PIXEL_FORMAT_YCbCr_422_I:
1259 case HAL_PIXEL_FORMAT_YCbCr_422_P:
1260 case HAL_PIXEL_FORMAT_YCbCr_420_P:
1261 case HAL_PIXEL_FORMAT_YCbCr_420_I:
1262 case HAL_PIXEL_FORMAT_CbYCrY_422_I:
1263 case HAL_PIXEL_FORMAT_CbYCrY_420_I:
1264 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1265 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
1266 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
1267 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
1268 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
1269 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
1270 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
1271 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
1272 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
1273 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
1274 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
1275 return 1;
codeworkx62f02ba2012-05-20 12:00:36 +02001276 default:
codeworkx62f02ba2012-05-20 12:00:36 +02001277 return 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001278 }
codeworkx62f02ba2012-05-20 12:00:36 +02001279}