blob: 6351bbf3138c05cfe9929b71597abf1e6c279100 [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;
108 default:
109 SEC_HWC_Log(HWC_LOG_ERROR, "%s::id(%d) is weird", __func__, id);
110 goto error;
111}
112
113// 0/10
114// snprintf(name, 64, device_template, id + 3);
115// 5/10
116// snprintf(name, 64, device_template, id + 0);
117// 0/10
118// snprintf(name, 64, device_template, id + 1);
119 snprintf(name, 64, device_template, real_id);
120
121 win->fd = open(name, O_RDWR);
122 if (win->fd <= 0) {
123 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Failed to open window device (%s) : %s",
124 __func__, strerror(errno), name);
125 goto error;
126 }
127
128#ifdef ENABLE_FIMD_VSYNC
129 if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0) {
130 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
131 goto error;
132 }
133#endif
134
135 return 0;
136
137error:
138 if (0 < win->fd)
139 close(win->fd);
140 win->fd = 0;
141
142 return -1;
143}
144
145int window_close(struct hwc_win_info_t *win)
146{
147 int ret = 0;
148
149 if (0 < win->fd) {
150
codeworkx62f02ba2012-05-20 12:00:36 +0200151#ifdef ENABLE_FIMD_VSYNC
152 int vsync = 0;
153 if (ioctl(win->fd, S3CFB_SET_VSYNC_INT, &vsync) < 0)
154 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_SET_VSYNC_INT fail", __func__);
155#endif
156 ret = close(win->fd);
157 }
158 win->fd = 0;
159
160 return ret;
161}
162
163int window_set_pos(struct hwc_win_info_t *win)
164{
165 struct s3cfb_user_window window;
166
167 //before changing the screen configuration...powerdown the window
168 if (window_hide(win) != 0)
169 return -1;
170
171 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: x(%d), y(%d)",
172 __func__, win->rect_info.x, win->rect_info.y);
173
174 win->var_info.xres_virtual = (win->lcd_info.xres + 15) & ~ 15;
175 win->var_info.yres_virtual = win->lcd_info.yres * NUM_OF_WIN_BUF;
176 win->var_info.xres = win->rect_info.w;
177 win->var_info.yres = win->rect_info.h;
178
179 win->var_info.activate &= ~FB_ACTIVATE_MASK;
180 win->var_info.activate |= FB_ACTIVATE_FORCE;
181
182 if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) {
183 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPUT_VSCREENINFO(%d, %d) fail",
184 __func__, win->rect_info.w, win->rect_info.h);
185 return -1;
186 }
187
188 window.x = win->rect_info.x;
189 window.y = win->rect_info.y;
190
191 if (ioctl(win->fd, S3CFB_WIN_POSITION, &window) < 0) {
192 SEC_HWC_Log(HWC_LOG_ERROR, "%s::S3CFB_WIN_POSITION(%d, %d) fail",
193 __func__, window.x, window.y);
194 return -1;
195 }
196
197 return 0;
198}
199
200int window_get_info(struct hwc_win_info_t *win, int win_num)
201{
202 int temp_size = 0;
203
204 if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) {
205 SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_FSCREENINFO failed : %s",
206 strerror(errno));
207 goto error;
208 }
209
210 win->size = win->fix_info.line_length * win->var_info.yres;
211
codeworkx62f02ba2012-05-20 12:00:36 +0200212 for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
213 temp_size = win->size * j;
codeworkx62f02ba2012-05-20 12:00:36 +0200214 win->addr[j] = win->fix_info.smem_start + temp_size;
codeworkx62f02ba2012-05-20 12:00:36 +0200215 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::win-%d add[%d] %x ",
216 __func__, win_num, j, win->addr[j]);
217 }
218 return 0;
219
220error:
221 win->fix_info.smem_start = 0;
222
223 return -1;
224}
225
226int window_pan_display(struct hwc_win_info_t *win)
227{
228 struct fb_var_screeninfo *lcd_info = &(win->lcd_info);
229
230#ifdef ENABLE_FIMD_VSYNC
codeworkx62f02ba2012-05-20 12:00:36 +0200231 if (ioctl(win->fd, FBIO_WAITFORVSYNC, 0) < 0)
232 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIO_WAITFORVSYNC fail(%s)",
233 __func__, strerror(errno));
234#endif
codeworkx62f02ba2012-05-20 12:00:36 +0200235
236 lcd_info->yoffset = lcd_info->yres * win->buf_index;
237
238 if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) {
239 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)",
240 __func__,
241 lcd_info->yres,
242 win->buf_index, lcd_info->yres_virtual,
243 strerror(errno));
244 return -1;
245 }
246 return 0;
247}
248
249int window_show(struct hwc_win_info_t *win)
250{
251 if (win->power_state == 0) {
252 if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
253 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
254 __func__, win->fd, strerror(errno));
255 return -1;
256 }
257 win->power_state = 1;
258 }
259 return 0;
260}
261
262int window_hide(struct hwc_win_info_t *win)
263{
264 if (win->power_state == 1) {
265 if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
266 SEC_HWC_Log(HWC_LOG_ERROR, "%s::FBIOBLANK failed : (%d:%s)",
267 __func__, win->fd, strerror(errno));
268 return -1;
269 }
270 win->power_state = 0;
271 }
272 return 0;
273}
274
275int window_get_global_lcd_info(int fd, struct fb_var_screeninfo *lcd_info)
276{
277 if (ioctl(fd, FBIOGET_VSCREENINFO, lcd_info) < 0) {
278 SEC_HWC_Log(HWC_LOG_ERROR, "FBIOGET_VSCREENINFO failed : %s",
279 strerror(errno));
280 return -1;
281 }
282
283 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: Default LCD x(%d),y(%d)",
284 __func__, lcd_info->xres, lcd_info->yres);
285 return 0;
286}
287
288int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src)
289{
290 struct v4l2_format fmt;
291 struct v4l2_cropcap cropcap;
292 struct v4l2_crop crop;
293 struct v4l2_requestbuffers req;
294
codeworkx62f02ba2012-05-20 12:00:36 +0200295 fmt.fmt.pix.width = src->full_width;
296 fmt.fmt.pix.height = src->full_height;
297 fmt.fmt.pix.pixelformat = src->color_space;
298 fmt.fmt.pix.field = V4L2_FIELD_NONE;
codeworkx62f02ba2012-05-20 12:00:36 +0200299 fmt.type = V4L2_BUF_TYPE_OUTPUT;
300
301 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
302 SEC_HWC_Log(HWC_LOG_ERROR, "%s::VIDIOC_S_FMT failed : errno=%d (%s)"
303 " : fd=%d\n", __func__, errno, strerror(errno), fd);
304 return -1;
305 }
306
307 /* crop input size */
308 crop.type = V4L2_BUF_TYPE_OUTPUT;
309 crop.c.width = src->width;
310 crop.c.height = src->height;
codeworkx62f02ba2012-05-20 12:00:36 +0200311 if (0x50 <= hw_ver) {
312 crop.c.left = src->start_x;
313 crop.c.top = src->start_y;
314 } else {
315 crop.c.left = 0;
316 crop.c.top = 0;
317 }
318
codeworkx62f02ba2012-05-20 12:00:36 +0200319 if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
320 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_CROP :"
321 "crop.c.left : (%d), crop.c.top : (%d), crop.c.width : (%d), crop.c.height : (%d)",
322 __func__, crop.c.left, crop.c.top, crop.c.width, crop.c.height);
323 return -1;
324 }
325
326 /* input buffer type */
327 req.count = 1;
328 req.memory = V4L2_MEMORY_USERPTR;
329 req.type = V4L2_BUF_TYPE_OUTPUT;
330
331 if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
332 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in VIDIOC_REQBUFS", __func__);
333 return -1;
334 }
335
336 return 0;
337}
338
339int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst,
340 int rotation, int hflip, int vflip, unsigned int addr)
341{
342 struct v4l2_format sFormat;
343 struct v4l2_control vc;
344 struct v4l2_framebuffer fbuf;
codeworkx62f02ba2012-05-20 12:00:36 +0200345 int ret;
346
codeworkx62f02ba2012-05-20 12:00:36 +0200347 /* set rotation configuration */
codeworkx62f02ba2012-05-20 12:00:36 +0200348 vc.id = V4L2_CID_ROTATION;
codeworkx62f02ba2012-05-20 12:00:36 +0200349 vc.value = rotation;
350
351 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
352 if (ret < 0) {
353 SEC_HWC_Log(HWC_LOG_ERROR,
354 "%s::Error in video VIDIOC_S_CTRL - rotation (%d)"
355 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
356 return -1;
357 }
358
359 vc.id = V4L2_CID_HFLIP;
360 vc.value = hflip;
361
362 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
363 if (ret < 0) {
364 SEC_HWC_Log(HWC_LOG_ERROR,
365 "%s::Error in video VIDIOC_S_CTRL - hflip (%d)"
366 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
367 return -1;
368 }
369
370 vc.id = V4L2_CID_VFLIP;
371 vc.value = vflip;
372
373 ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
374 if (ret < 0) {
375 SEC_HWC_Log(HWC_LOG_ERROR,
376 "%s::Error in video VIDIOC_S_CTRL - vflip (%d)"
377 "vc.id : (%d), vc.value : (%d)", __func__, ret, vc.id, vc.value);
378 return -1;
379 }
380
codeworkx62f02ba2012-05-20 12:00:36 +0200381 /* set size, format & address for destination image (DMA-OUTPUT) */
382 ret = ioctl(fd, VIDIOC_G_FBUF, &fbuf);
383 if (ret < 0) {
384 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FBUF (%d)", __func__, ret);
385 return -1;
386 }
387
388 fbuf.base = (void *)addr;
389 fbuf.fmt.width = dst->full_width;
390 fbuf.fmt.height = dst->full_height;
391 fbuf.fmt.pixelformat = dst->color_space;
392
393 ret = ioctl(fd, VIDIOC_S_FBUF, &fbuf);
394 if (ret < 0) {
395 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FBUF (%d)", __func__, ret);
396 return -1;
397 }
398
399 /* set destination window */
400 sFormat.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
401 sFormat.fmt.win.w.left = dst->start_x;
402 sFormat.fmt.win.w.top = dst->start_y;
403 sFormat.fmt.win.w.width = dst->width;
404 sFormat.fmt.win.w.height = dst->height;
405
406 ret = ioctl(fd, VIDIOC_S_FMT, &sFormat);
407 if (ret < 0) {
408 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_S_FMT (%d)", __func__, ret);
409 return -1;
410 }
codeworkx62f02ba2012-05-20 12:00:36 +0200411
412 return 0;
413}
414
415int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
416{
417 if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) {
418 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMON\n");
419 return -1;
420 }
421
422 return 0;
423}
424
425int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type, int index)
426{
codeworkx62f02ba2012-05-20 12:00:36 +0200427 struct v4l2_buffer buf;
428 int ret;
429
codeworkx62f02ba2012-05-20 12:00:36 +0200430 buf.length = 0;
431 buf.m.userptr = (unsigned long)fimc_buf;
codeworkx62f02ba2012-05-20 12:00:36 +0200432 buf.memory = V4L2_MEMORY_USERPTR;
433 buf.index = index;
434 buf.type = type;
435
codeworkx62f02ba2012-05-20 12:00:36 +0200436 ret = ioctl(fd, VIDIOC_QBUF, &buf);
437 if (0 > ret) {
438 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_QBUF : (%d)", ret);
439 return -1;
440 }
441
442 return 0;
443}
444
445int fimc_v4l2_dequeue(int fd, struct fimc_buf *fimc_buf, enum v4l2_buf_type type)
446{
447 struct v4l2_buffer buf;
codeworkx62f02ba2012-05-20 12:00:36 +0200448
codeworkx62f02ba2012-05-20 12:00:36 +0200449 buf.memory = V4L2_MEMORY_USERPTR;
450 buf.type = type;
451
452 if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) {
453 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_DQBUF\n");
454 return -1;
455 }
456
457 return buf.index;
458}
459
460int fimc_v4l2_stream_off(int fd, enum v4l2_buf_type type)
461{
462 if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) {
463 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_STREAMOFF\n");
464 return -1;
465 }
466
467 return 0;
468}
469
470int fimc_v4l2_clr_buf(int fd, enum v4l2_buf_type type)
471{
472 struct v4l2_requestbuffers req;
473
474 req.count = 0;
475 req.memory = V4L2_MEMORY_USERPTR;
476 req.type = type;
477
478 if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
479 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_REQBUFS");
480 }
481
482 return 0;
483}
484
485int fimc_v4l2_S_ctrl(int fd)
486{
487 struct v4l2_control vc;
488
489 vc.id = V4L2_CID_CACHEABLE;
490 vc.value = 1;
491
492 if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
493 SEC_HWC_Log(HWC_LOG_ERROR, "Error in VIDIOC_S_CTRL");
494 return -1;
495 }
496
497 return 0;
498}
499
500int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_src_buf, struct fimc_buf *fimc_dst_buf)
501{
502#ifdef CHECK_FPS
503 check_fps();
504#endif
505
codeworkx62f02ba2012-05-20 12:00:36 +0200506 if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
507 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_on()");
508 return -5;
509 }
510
511 if (fimc_v4l2_queue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT, 0) < 0) {
512 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_queue()");
513 goto STREAM_OFF;
514 }
codeworkx62f02ba2012-05-20 12:00:36 +0200515 if (fimc_v4l2_dequeue(fd, fimc_src_buf, V4L2_BUF_TYPE_OUTPUT) < 0) {
516 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_dequeue()");
517 return -6;
518 }
codeworkx62f02ba2012-05-20 12:00:36 +0200519STREAM_OFF:
520 if (fimc_v4l2_stream_off(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
521 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_stream_off()");
522 return -8;
523 }
codeworkx62f02ba2012-05-20 12:00:36 +0200524 if (fimc_v4l2_clr_buf(fd, V4L2_BUF_TYPE_OUTPUT) < 0) {
525 SEC_HWC_Log(HWC_LOG_ERROR, "Fail : SRC v4l2_clr_buf()");
526 return -10;
527 }
codeworkx62f02ba2012-05-20 12:00:36 +0200528 return 0;
529}
530
531static int memcpy_rect(void *dst, void *src, int fullW, int fullH, int realW, int realH, int format)
532{
533 unsigned char *srcCb, *srcCr;
534 unsigned char *dstCb, *dstCr;
535 unsigned char *srcY, *dstY;
536 int srcCbOffset, srcCrOffset;
537 int dstCbOffset, dstFrameOffset, dstCrOffset;
538 int cbFullW, cbRealW, cbFullH, cbRealH;
539 int ySrcFW, ySrcFH, ySrcRW, ySrcRH;
540 int planes;
541 int i;
542
543 SEC_HWC_Log(HWC_LOG_DEBUG,
544 "++memcpy_rect()::"
545 "dst(0x%x),src(0x%x),f.w(%d),f.h(%d),r.w(%d),r.h(%d),format(0x%x)",
546 (unsigned int)dst, (unsigned int)src, fullW, fullH, realW, realH, format);
547
548// Set dst Y, Cb, Cr address for FIMC
549 {
550 cbFullW = fullW >> 1;
551 cbRealW = realW >> 1;
552 cbFullH = fullH >> 1;
553 cbRealH = realH >> 1;
554 dstFrameOffset = fullW * fullH;
555 dstCrOffset = cbFullW * cbFullH;
556 dstY = (unsigned char *)dst;
557 dstCb = (unsigned char *)dst + dstFrameOffset;
558 dstCr = (unsigned char *)dstCb + dstCrOffset;
559 }
560
561// Get src Y, Cb, Cr address for source buffer.
562// Each address is aligned by 16's multiple for GPU both width and height.
563 {
564 ySrcFW = fullW;
565 ySrcFH = fullH;
566 ySrcRW = realW;
567 ySrcRH = realH;
568 srcCbOffset = EXYNOS4_ALIGN(ySrcRW,16)* EXYNOS4_ALIGN(ySrcRH,16);
569 srcCrOffset = EXYNOS4_ALIGN(cbRealW,16)* EXYNOS4_ALIGN(cbRealH,16);
570 srcY = (unsigned char *)src;
571 srcCb = (unsigned char *)src + srcCbOffset;
572 srcCr = (unsigned char *)srcCb + srcCrOffset;
573 }
574 SEC_HWC_Log(HWC_LOG_DEBUG,
575 "--memcpy_rect()::\n"
576 "dstY(0x%x),dstCb(0x%x),dstCr(0x%x) \n"
577 "srcY(0x%x),srcCb(0x%x),srcCr(0x%x) \n"
578 "cbRealW(%d),cbRealH(%d)",
579 (unsigned int)dstY,(unsigned int)dstCb,(unsigned int)dstCr,
580 (unsigned int)srcY,(unsigned int)srcCb,(unsigned int)srcCr,
581 cbRealW, cbRealH);
582
583 if (format == HAL_PIXEL_FORMAT_YV12) { //YV12(Y,Cr,Cv)
584 planes = 3;
585//This is code for VE, deleted temporory by SSONG 2011.09.22
586// This will be enabled later.
587/*
588 //as defined in hardware.h, cb & cr full_width should be aligned to 16. ALIGN(y_stride/2, 16).
589 ////Alignment is hard coded to 16.
590 ////for example...check frameworks/media/libvideoeditor/lvpp/VideoEditorTools.cpp file for UV stride cal
591 cbSrcFW = (cbSrcFW + 15) & (~15);
592 srcCbOffset = ySrcFW * fullH;
593 srcCrOffset = srcCbOffset + ((cbSrcFW * fullH) >> 1);
594 srcY = (unsigned char *)src;
595 srcCb = (unsigned char *)src + srcCbOffset;
596 srcCr = (unsigned char *)src + srcCrOffset;
597*/
598 } else if ((format == HAL_PIXEL_FORMAT_YCbCr_420_P)) {
599 planes = 3;
600 } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
601 planes = 2;
602 } else {
603 SEC_HWC_Log(HWC_LOG_ERROR, "use default memcpy instead of memcpy_rect");
604 return -1;
605 }
606//#define CHECK_PERF
607#ifdef CHECK_PERF
608 struct timeval start, end;
609 gettimeofday(&start, NULL);
610#endif
611 for (i = 0; i < realH; i++)
612 memcpy(dstY + fullW * i, srcY + ySrcFW * i, ySrcRW);
613 if (planes == 2) {
614 for (i = 0; i < cbRealH; i++)
615 memcpy(dstCb + ySrcFW * i, srcCb + ySrcFW * i, ySrcRW);
616 } else if (planes == 3) {
617 for (i = 0; i < cbRealH; i++)
618 memcpy(dstCb + cbFullW * i, srcCb + cbFullW * i, cbRealW);
619 for (i = 0; i < cbRealH; i++)
620 memcpy(dstCr + cbFullW * i, srcCr + cbFullW * i, cbRealW);
621 }
622#ifdef CHECK_PERF
623 gettimeofday(&end, NULL);
624 SEC_HWC_Log(HWC_LOG_ERROR, "[COPY]=%d,",(end.tv_sec - start.tv_sec)*1000+(end.tv_usec - start.tv_usec)/1000);
625#endif
626
627 return 0;
628}
629
630/*****************************************************************************/
631static int get_src_phys_addr(struct hwc_context_t *ctx,
632 sec_img *src_img, sec_rect *src_rect)
633{
634 s5p_fimc_t *fimc = &ctx->fimc;
codeworkx62f02ba2012-05-20 12:00:36 +0200635
636 unsigned int src_virt_addr = 0;
637 unsigned int src_phys_addr = 0;
638 unsigned int src_frame_size = 0;
639
codeworkx62f02ba2012-05-20 12:00:36 +0200640 ADDRS * addr;
641
642 // error check routine
643 if (0 == src_img->base && !(src_img->usage & GRALLOC_USAGE_HW_FIMC1)) {
644 SEC_HWC_Log(HWC_LOG_ERROR, "%s invalid src image base\n", __func__);
645 return 0;
646 }
647
648 switch (src_img->mem_type) {
649 case HWC_PHYS_MEM_TYPE:
650 src_phys_addr = src_img->base + src_img->offset;
651 break;
652
653 case HWC_VIRT_MEM_TYPE:
654 case HWC_UNKNOWN_MEM_TYPE:
655 switch (src_img->format) {
656 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
657 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
658 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
659 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
660 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
661 addr = (ADDRS *)(src_img->base);
662 fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
663 fimc->params.src.buf_addr_phy_cb = addr->addr_cbcr;
664
665 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
666 if (0 == src_phys_addr) {
667 SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
668 "(format=CUSTOM_YCbCr/YCrCb_420_SP Y-addr=0x%x "
669 "CbCr-Addr=0x%x)",
670 __func__, fimc->params.src.buf_addr_phy_rgb_y,
671 fimc->params.src.buf_addr_phy_cb);
672 return 0;
673 }
674 break;
675 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
676 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
677 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
678 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
679 addr = (ADDRS *)(src_img->base + src_img->offset);
680 fimc->params.src.buf_addr_phy_rgb_y = addr->addr_y;
681 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
682 if (0 == src_phys_addr) {
683 SEC_HWC_Log(HWC_LOG_ERROR, "%s address error "
684 "(format=CUSTOM_YCbCr/CbYCrY_422_I Y-addr=0x%x)",
685 __func__, fimc->params.src.buf_addr_phy_rgb_y);
686 return 0;
687 }
688 break;
689 default:
codeworkx62f02ba2012-05-20 12:00:36 +0200690 if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
691 fimc->params.src.buf_addr_phy_rgb_y = src_img->paddr;
692 fimc->params.src.buf_addr_phy_cb = src_img->paddr + src_img->uoffset;
693 fimc->params.src.buf_addr_phy_cr = src_img->paddr + src_img->uoffset + src_img->voffset;
694 src_phys_addr = fimc->params.src.buf_addr_phy_rgb_y;
codeworkx62f02ba2012-05-20 12:00:36 +0200695 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100696 SEC_HWC_Log(HWC_LOG_ERROR, "%s::\nformat = 0x%x : Not "
697 "GRALLOC_USAGE_HW_FIMC1 can not supported\n",
698 __func__, src_img->format);
codeworkx62f02ba2012-05-20 12:00:36 +0200699 }
codeworkx62f02ba2012-05-20 12:00:36 +0200700 break;
701 }
702 }
703
704 return src_phys_addr;
705}
706
codeworkx62f02ba2012-05-20 12:00:36 +0200707static inline int rotateValueHAL2PP(unsigned char transform)
708{
709 int rotate_flag = transform & 0x7;
710
711 switch (rotate_flag) {
712 case HAL_TRANSFORM_ROT_90: return 90;
713 case HAL_TRANSFORM_ROT_180: return 180;
714 case HAL_TRANSFORM_ROT_270: return 270;
715 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90: return 90;
716 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90: return 90;
717 case HAL_TRANSFORM_FLIP_H: return 0;
718 case HAL_TRANSFORM_FLIP_V: return 0;
719 }
720 return 0;
721}
722
723static inline int hflipValueHAL2PP(unsigned char transform)
724{
725 int flip_flag = transform & 0x7;
726 switch (flip_flag) {
727 case HAL_TRANSFORM_FLIP_H:
728 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
729 return 1;
730 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
731 case HAL_TRANSFORM_ROT_90:
732 case HAL_TRANSFORM_ROT_180:
733 case HAL_TRANSFORM_ROT_270:
734 case HAL_TRANSFORM_FLIP_V:
735 break;
736 }
737 return 0;
738}
739
740static inline int vflipValueHAL2PP(unsigned char transform)
741{
742 int flip_flag = transform & 0x7;
743 switch (flip_flag) {
744 case HAL_TRANSFORM_FLIP_V:
745 case HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90:
746 return 1;
747 case HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90:
748 case HAL_TRANSFORM_ROT_90:
749 case HAL_TRANSFORM_ROT_180:
750 case HAL_TRANSFORM_ROT_270:
751 case HAL_TRANSFORM_FLIP_H:
752 break;
753 }
754 return 0;
755}
756
757static inline int multipleOf2(int number)
758{
759 if (number % 2 == 1)
760 return (number - 1);
761 else
762 return number;
763}
764
765static inline int multipleOf4(int number)
766{
767 int remain_number = number % 4;
768
769 if (remain_number != 0)
770 return (number - remain_number);
771 else
772 return number;
773}
774
775static inline int multipleOf8(int number)
776{
777 int remain_number = number % 8;
778
779 if (remain_number != 0)
780 return (number - remain_number);
781 else
782 return number;
783}
784
785static inline int multipleOf16(int number)
786{
787 int remain_number = number % 16;
788
789 if (remain_number != 0)
790 return (number - remain_number);
791 else
792 return number;
793}
794
795static inline int widthOfPP(unsigned int ver, int pp_color_format, int number)
796{
codeworkx62f02ba2012-05-20 12:00:36 +0200797 if (0x50 <= ver) {
codeworkx62f02ba2012-05-20 12:00:36 +0200798 switch (pp_color_format) {
799 /* 422 1/2/3 plane */
800 case V4L2_PIX_FMT_YUYV:
801 case V4L2_PIX_FMT_UYVY:
802 case V4L2_PIX_FMT_NV61:
803 case V4L2_PIX_FMT_NV16:
804 case V4L2_PIX_FMT_YUV422P:
805
806 /* 420 2/3 plane */
807 case V4L2_PIX_FMT_NV21:
808 case V4L2_PIX_FMT_NV12:
809 case V4L2_PIX_FMT_NV12T:
810 case V4L2_PIX_FMT_YUV420:
811 return multipleOf2(number);
812
813 default :
814 return number;
815 }
816 } else {
817 switch (pp_color_format) {
818 case V4L2_PIX_FMT_RGB565:
819 return multipleOf8(number);
820
821 case V4L2_PIX_FMT_RGB32:
822 return multipleOf4(number);
823
824 case V4L2_PIX_FMT_YUYV:
825 case V4L2_PIX_FMT_UYVY:
826 return multipleOf4(number);
827
828 case V4L2_PIX_FMT_NV61:
829 case V4L2_PIX_FMT_NV16:
830 return multipleOf8(number);
831
832 case V4L2_PIX_FMT_YUV422P:
833 return multipleOf16(number);
834
835 case V4L2_PIX_FMT_NV21:
836 case V4L2_PIX_FMT_NV12:
837 case V4L2_PIX_FMT_NV12T:
838 return multipleOf8(number);
839
840 case V4L2_PIX_FMT_YUV420:
841 return multipleOf16(number);
842
843 default :
844 return number;
845 }
846 }
847 return number;
848}
849
850static inline int heightOfPP(int pp_color_format, int number)
851{
852 switch (pp_color_format) {
853 case V4L2_PIX_FMT_NV21:
854 case V4L2_PIX_FMT_NV12:
855 case V4L2_PIX_FMT_NV12T:
856 case V4L2_PIX_FMT_YUV420:
857 return multipleOf2(number);
858
859 default :
860 return number;
861 break;
862 }
863 return number;
864}
865
866static unsigned int get_yuv_bpp(unsigned int fmt)
867{
868 int i, sel = -1;
869
870 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
871 if (yuv_list[i].fmt == fmt) {
872 sel = i;
873 break;
874 }
875 }
876
877 if (sel == -1)
878 return sel;
879 else
880 return yuv_list[sel].bpp;
881}
882
883static unsigned int get_yuv_planes(unsigned int fmt)
884{
885 int i, sel = -1;
886
887 for (i = 0; i < (int)(sizeof(yuv_list) / sizeof(struct yuv_fmt_list)); i++) {
888 if (yuv_list[i].fmt == fmt) {
889 sel = i;
890 break;
891 }
892 }
893
894 if (sel == -1)
895 return sel;
896 else
897 return yuv_list[sel].planes;
898}
899
espenfjo34f9d5d2012-12-01 18:52:36 +0100900static int runFimcCore(struct hwc_context_t *ctx,
codeworkx62f02ba2012-05-20 12:00:36 +0200901 unsigned int src_phys_addr, sec_img *src_img, sec_rect *src_rect,
902 uint32_t src_color_space,
903 unsigned int dst_phys_addr, sec_img *dst_img, sec_rect *dst_rect,
904 uint32_t dst_color_space, int transform)
905{
906 s5p_fimc_t * fimc = &ctx->fimc;
907 s5p_fimc_params_t * params = &(fimc->params);
908
909 struct fimc_buf fimc_src_buf;
910 int src_bpp, src_planes;
911
codeworkx62f02ba2012-05-20 12:00:36 +0200912 unsigned int frame_size = 0;
913
914 bool src_cbcr_order = true;
915 int rotate_value = rotateValueHAL2PP(transform);
espenfjo34f9d5d2012-12-01 18:52:36 +0100916 int hflip = 0;
917 int vflip = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200918
919 /* 1. param(fimc config)->src information
920 * - src_img,src_rect => s_fw,s_fh,s_w,s_h,s_x,s_y
921 */
922 params->src.full_width = src_img->f_w;
923 params->src.full_height = src_img->f_h;
924 params->src.width = src_rect->w;
925 params->src.height = src_rect->h;
926 params->src.start_x = src_rect->x;
927 params->src.start_y = src_rect->y;
928 params->src.color_space = src_color_space;
929 params->src.buf_addr_phy_rgb_y = src_phys_addr;
930
codeworkx62f02ba2012-05-20 12:00:36 +0200931 /* check src minimum */
932 if (src_rect->w < 16 || src_rect->h < 8) {
933 SEC_HWC_Log(HWC_LOG_ERROR,
934 "%s src size is not supported by fimc : f_w=%d f_h=%d "
935 "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
936 params->src.full_width, params->src.full_height,
937 params->src.start_x, params->src.start_y,
938 params->src.width, params->src.height,
939 src_rect->w, src_rect->h,
940 params->src.color_space);
941 return -1;
942 }
943
codeworkx62f02ba2012-05-20 12:00:36 +0200944 /* 2. param(fimc config)->dst information
945 * - dst_img,dst_rect,rot => d_fw,d_fh,d_w,d_h,d_x,d_y
946 */
947 switch (rotate_value) {
948 case 0:
espenfjo34f9d5d2012-12-01 18:52:36 +0100949 hflip = hflipValueHAL2PP(transform);
950 vflip = vflipValueHAL2PP(transform);
codeworkx62f02ba2012-05-20 12:00:36 +0200951 params->dst.full_width = dst_img->f_w;
952 params->dst.full_height = dst_img->f_h;
953
954 params->dst.start_x = dst_rect->x;
955 params->dst.start_y = dst_rect->y;
956
957 params->dst.width =
958 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
959 params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
960 break;
961 case 90:
espenfjo34f9d5d2012-12-01 18:52:36 +0100962 hflip = vflipValueHAL2PP(transform);
963 vflip = hflipValueHAL2PP(transform);
codeworkx62f02ba2012-05-20 12:00:36 +0200964 params->dst.full_width = dst_img->f_h;
965 params->dst.full_height = dst_img->f_w;
966
967 params->dst.start_x = dst_rect->y;
968 params->dst.start_y = dst_img->f_w - (dst_rect->x + dst_rect->w);
969
970 params->dst.width =
971 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
972 params->dst.height =
973 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
974
975 if (0x50 > fimc->hw_ver)
976 params->dst.start_y += (dst_rect->w - params->dst.height);
977 break;
978 case 180:
979 params->dst.full_width = dst_img->f_w;
980 params->dst.full_height = dst_img->f_h;
981
982 params->dst.start_x = dst_img->f_w - (dst_rect->x + dst_rect->w);
983 params->dst.start_y = dst_img->f_h - (dst_rect->y + dst_rect->h);
984
985 params->dst.width =
986 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
987 params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
988 break;
989 case 270:
990 params->dst.full_width = dst_img->f_h;
991 params->dst.full_height = dst_img->f_w;
992
993 params->dst.start_x = dst_img->f_h - (dst_rect->y + dst_rect->h);
994 params->dst.start_y = dst_rect->x;
995
996 params->dst.width =
997 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
998 params->dst.height =
999 widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
1000
1001 if (0x50 > fimc->hw_ver)
1002 params->dst.start_y += (dst_rect->w - params->dst.height);
1003 break;
1004 }
1005 params->dst.color_space = dst_color_space;
codeworkx62f02ba2012-05-20 12:00:36 +02001006
1007 SEC_HWC_Log(HWC_LOG_DEBUG,
espenfjo34f9d5d2012-12-01 18:52:36 +01001008 "runFimcCore()::"
codeworkx62f02ba2012-05-20 12:00:36 +02001009 "SRC f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)=>"
1010 "DST f.w(%d),f.h(%d),x(%d),y(%d),w(%d),h(%d)",
1011 params->src.full_width, params->src.full_height,
1012 params->src.start_x, params->src.start_y,
1013 params->src.width, params->src.height,
1014 params->dst.full_width, params->dst.full_height,
1015 params->dst.start_x, params->dst.start_y,
1016 params->dst.width, params->dst.height);
1017
1018 /* check dst minimum */
1019 if (dst_rect->w < 8 || dst_rect->h < 4) {
1020 SEC_HWC_Log(HWC_LOG_ERROR,
1021 "%s dst size is not supported by fimc : f_w=%d f_h=%d "
1022 "x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
1023 params->dst.full_width, params->dst.full_height,
1024 params->dst.start_x, params->dst.start_y,
1025 params->dst.width, params->dst.height,
1026 dst_rect->w, dst_rect->h, params->dst.color_space);
1027 return -1;
1028 }
1029 /* check scaling limit
1030 * the scaling limie must not be more than MAX_RESIZING_RATIO_LIMIT
1031 */
1032 if (((src_rect->w > dst_rect->w) &&
1033 ((src_rect->w / dst_rect->w) > MAX_RESIZING_RATIO_LIMIT)) ||
1034 ((dst_rect->w > src_rect->w) &&
1035 ((dst_rect->w / src_rect->w) > MAX_RESIZING_RATIO_LIMIT))) {
1036 SEC_HWC_Log(HWC_LOG_ERROR,
1037 "%s over scaling limit : src.w=%d dst.w=%d (limit=%d)",
1038 __func__, src_rect->w, dst_rect->w, MAX_RESIZING_RATIO_LIMIT);
1039 return -1;
1040 }
1041
1042 /* 3. Set configuration related to destination (DMA-OUT)
1043 * - set input format & size
1044 * - crop input size
1045 * - set input buffer
1046 * - set buffer type (V4L2_MEMORY_USERPTR)
1047 */
codeworkx62f02ba2012-05-20 12:00:36 +02001048
1049 if (fimc_v4l2_set_dst(fimc->dev_fd, &params->dst, rotate_value, hflip, vflip, dst_phys_addr) < 0) {
1050 SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_dst is failed\n");
1051 return -1;
1052 }
1053
1054 /* 4. Set configuration related to source (DMA-INPUT)
1055 * - set input format & size
1056 * - crop input size
1057 * - set input buffer
1058 * - set buffer type (V4L2_MEMORY_USERPTR)
1059 */
codeworkx62f02ba2012-05-20 12:00:36 +02001060 if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, &params->src) < 0) {
1061 SEC_HWC_Log(HWC_LOG_ERROR, "fimc_v4l2_set_src is failed\n");
1062 return -1;
1063 }
codeworkx62f02ba2012-05-20 12:00:36 +02001064
1065 /* 5. Set input dma address (Y/RGB, Cb, Cr)
1066 * - zero copy : mfc, camera
codeworkx62f02ba2012-05-20 12:00:36 +02001067 */
1068 switch (src_img->format) {
1069 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
1070 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
1071 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
1072 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
1073 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
1074 /* for video contents zero copy case */
1075 fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
1076 fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
1077 break;
1078
1079 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
1080 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
1081 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
1082 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
1083 case HAL_PIXEL_FORMAT_RGB_565:
1084 case HAL_PIXEL_FORMAT_YV12:
1085 default:
espenfjo34f9d5d2012-12-01 18:52:36 +01001086 if (src_img->format == HAL_PIXEL_FORMAT_YV12){
codeworkx62f02ba2012-05-20 12:00:36 +02001087 src_cbcr_order = false;
codeworkx62f02ba2012-05-20 12:00:36 +02001088 }
codeworkx62f02ba2012-05-20 12:00:36 +02001089
1090 if (src_img->usage & GRALLOC_USAGE_HW_FIMC1) {
1091 fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
1092 if (src_cbcr_order == true) {
1093 fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
1094 fimc_src_buf.base[2] = params->src.buf_addr_phy_cr;
1095 }
1096 else {
1097 fimc_src_buf.base[2] = params->src.buf_addr_phy_cb;
1098 fimc_src_buf.base[1] = params->src.buf_addr_phy_cr;
1099 }
1100 SEC_HWC_Log(HWC_LOG_DEBUG,
1101 "runFimcCore - Y=0x%X, U=0x%X, V=0x%X\n",
1102 fimc_src_buf.base[0], fimc_src_buf.base[1],fimc_src_buf.base[2]);
1103 break;
1104 }
codeworkx62f02ba2012-05-20 12:00:36 +02001105 }
1106
1107 /* 6. Run FIMC
1108 * - stream on => queue => dequeue => stream off => clear buf
1109 */
codeworkx62f02ba2012-05-20 12:00:36 +02001110 if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf, NULL) < 0) {
espenfjo34f9d5d2012-12-01 18:52:36 +01001111 ALOGE("fimcrun fail");
codeworkx62f02ba2012-05-20 12:00:36 +02001112 fimc_v4l2_clr_buf(fimc->dev_fd, V4L2_BUF_TYPE_OUTPUT);
1113 return -1;
1114 }
codeworkx62f02ba2012-05-20 12:00:36 +02001115
1116 return 0;
1117}
1118
codeworkx62f02ba2012-05-20 12:00:36 +02001119int createFimc(s5p_fimc_t *fimc)
1120{
1121 struct v4l2_capability cap;
1122 struct v4l2_format fmt;
1123 struct v4l2_control vc;
1124
1125 // open device file
1126 if (fimc->dev_fd <= 0)
1127 fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR);
1128
1129 if (fimc->dev_fd <= 0) {
1130 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Post processor open error (%d)",
1131 __func__, errno);
1132 goto err;
1133 }
1134
1135 // check capability
1136 if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) {
1137 SEC_HWC_Log(HWC_LOG_ERROR, "VIDIOC_QUERYCAP failed");
1138 goto err;
1139 }
1140
1141 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
1142 SEC_HWC_Log(HWC_LOG_ERROR, "%d has no streaming support", fimc->dev_fd);
1143 goto err;
1144 }
1145
1146 if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
1147 SEC_HWC_Log(HWC_LOG_ERROR, "%d is no video output", fimc->dev_fd);
1148 goto err;
1149 }
1150
1151 /*
1152 * malloc fimc_outinfo structure
1153 */
1154 fmt.type = V4L2_BUF_TYPE_OUTPUT;
1155 if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) {
1156 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_FMT", __func__);
1157 goto err;
1158 }
1159
codeworkx62f02ba2012-05-20 12:00:36 +02001160 vc.id = V4L2_CID_FIMC_VERSION;
1161 vc.value = 0;
1162
1163 if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) {
1164 SEC_HWC_Log(HWC_LOG_ERROR, "%s::Error in video VIDIOC_G_CTRL", __func__);
1165 goto err;
1166 }
1167 fimc->hw_ver = vc.value;
codeworkx62f02ba2012-05-20 12:00:36 +02001168
1169 return 0;
1170
1171err:
1172 if (0 < fimc->dev_fd)
1173 close(fimc->dev_fd);
1174 fimc->dev_fd =0;
1175
1176 return -1;
1177}
1178
1179int destroyFimc(s5p_fimc_t *fimc)
1180{
1181 if (fimc->out_buf.virt_addr != NULL) {
1182 fimc->out_buf.virt_addr = NULL;
1183 fimc->out_buf.length = 0;
1184 }
1185
1186 // close
1187 if (0 < fimc->dev_fd)
1188 close(fimc->dev_fd);
1189 fimc->dev_fd = 0;
1190
1191 return 0;
1192}
1193
1194int runFimc(struct hwc_context_t *ctx,
1195 struct sec_img *src_img, struct sec_rect *src_rect,
1196 struct sec_img *dst_img, struct sec_rect *dst_rect,
1197 uint32_t transform)
1198{
1199 s5p_fimc_t * fimc = &ctx->fimc;
1200
1201 unsigned int src_phys_addr = 0;
1202 unsigned int dst_phys_addr = 0;
1203 int rotate_value = 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001204 int32_t src_color_space;
1205 int32_t dst_color_space;
1206
1207 /* 1. source address and size */
1208 src_phys_addr = get_src_phys_addr(ctx, src_img, src_rect);
1209 if (0 == src_phys_addr)
1210 return -1;
1211
1212 /* 2. destination address and size */
espenfjo34f9d5d2012-12-01 18:52:36 +01001213 dst_phys_addr = dst_img->base;
codeworkx62f02ba2012-05-20 12:00:36 +02001214 if (0 == dst_phys_addr)
1215 return -2;
1216
1217 /* 3. check whether fimc supports the src format */
1218 src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format);
1219 if (0 > src_color_space)
1220 return -3;
1221 dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format);
1222 if (0 > dst_color_space)
1223 return -4;
1224
1225 /* 4. FIMC: src_rect of src_img => dst_rect of dst_img */
espenfjo34f9d5d2012-12-01 18:52:36 +01001226 if (runFimcCore(ctx, src_phys_addr, src_img, src_rect,
codeworkx62f02ba2012-05-20 12:00:36 +02001227 (uint32_t)src_color_space, dst_phys_addr, dst_img, dst_rect,
1228 (uint32_t)dst_color_space, transform) < 0)
1229 return -5;
1230
codeworkx62f02ba2012-05-20 12:00:36 +02001231 return 0;
1232}
1233
espenfjo34f9d5d2012-12-01 18:52:36 +01001234int check_yuv_format(unsigned int color_format) {
1235 switch (color_format) {
1236 case HAL_PIXEL_FORMAT_YV12:
1237 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1238 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1239 case HAL_PIXEL_FORMAT_YCbCr_422_I:
1240 case HAL_PIXEL_FORMAT_YCbCr_422_P:
1241 case HAL_PIXEL_FORMAT_YCbCr_420_P:
1242 case HAL_PIXEL_FORMAT_YCbCr_420_I:
1243 case HAL_PIXEL_FORMAT_CbYCrY_422_I:
1244 case HAL_PIXEL_FORMAT_CbYCrY_420_I:
1245 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1246 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
1247 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
1248 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
1249 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
1250 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
1251 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
1252 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
1253 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
1254 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
1255 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
1256 return 1;
codeworkx62f02ba2012-05-20 12:00:36 +02001257 default:
codeworkx62f02ba2012-05-20 12:00:36 +02001258 return 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001259 }
codeworkx62f02ba2012-05-20 12:00:36 +02001260}