1 /* 2 * Copyright (C) 2008 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 /* #define OVERLAY_DEBUG 1 */ 18 #define LOG_TAG "v4l2_utils" 19 20 #include <fcntl.h> 21 #include <errno.h> 22 #include <cutils/log.h> 23 #include <hardware/overlay.h> 24 #include <linux/videodev.h> 25 #include <sys/ioctl.h> 26 #include <sys/mman.h> 27 #include "v4l2_utils.h" 28 29 30 #define LOG_FUNCTION_NAME LOGV("%s: %s", __FILE__, __func__); 31 32 #define V4L2_CID_PRIV_OFFSET 0x0 33 #define V4L2_CID_PRIV_ROTATION (V4L2_CID_PRIVATE_BASE \ 34 + V4L2_CID_PRIV_OFFSET + 0) 35 #define V4L2_CID_PRIV_COLORKEY (V4L2_CID_PRIVATE_BASE \ 36 + V4L2_CID_PRIV_OFFSET + 1) 37 #define V4L2_CID_PRIV_COLORKEY_EN (V4L2_CID_PRIVATE_BASE \ 38 + V4L2_CID_PRIV_OFFSET + 2) 39 40 extern unsigned int g_lcd_width; 41 extern unsigned int g_lcd_height; 42 extern unsigned int g_lcd_bpp; 43 44 int v4l2_overlay_get(int name) 45 { 46 int result = -1; 47 switch (name) { 48 case OVERLAY_MINIFICATION_LIMIT: 49 result = 4; /* 0 = no limit */ 50 break; 51 case OVERLAY_MAGNIFICATION_LIMIT: 52 result = 2; /* 0 = no limit */ 53 break; 54 case OVERLAY_SCALING_FRAC_BITS: 55 result = 0; /* 0 = infinite */ 56 break; 57 case OVERLAY_ROTATION_STEP_DEG: 58 result = 90; /* 90 rotation steps (for instance) */ 59 break; 60 case OVERLAY_HORIZONTAL_ALIGNMENT: 61 result = 1; /* 1-pixel alignment */ 62 break; 63 case OVERLAY_VERTICAL_ALIGNMENT: 64 result = 1; /* 1-pixel alignment */ 65 break; 66 case OVERLAY_WIDTH_ALIGNMENT: 67 result = 1; /* 1-pixel alignment */ 68 break; 69 case OVERLAY_HEIGHT_ALIGNMENT: 70 result = 1; /* 1-pixel alignment */ 71 break; 72 } 73 return result; 74 } 75 76 int v4l2_overlay_open(int id) 77 { 78 LOG_FUNCTION_NAME 79 return open("/dev/video1", O_RDWR); 80 } 81 82 int v4l2_overlay_init_fimc(int fd, s5p_fimc_t *s5p_fimc) 83 { 84 int ret; 85 struct v4l2_control vc; 86 87 if (fd < 0) 88 return -1; 89 90 vc.id = V4L2_CID_FIMC_VERSION; 91 vc.value = 0; 92 93 s5p_fimc->dev_fd = fd; 94 95 ret = ioctl(s5p_fimc->dev_fd, VIDIOC_G_CTRL, &vc); 96 if (ret < 0) { 97 LOGE("Error in video VIDIOC_G_CTRL - V4L2_CID_FIMC_VERSION (%d)", ret); 98 LOGE("FIMC version is set with default"); 99 vc.value = 0x43; 100 } 101 s5p_fimc->hw_ver = vc.value; 102 return 0; 103 } 104 105 void dump_pixfmt(struct v4l2_pix_format *pix) 106 { 107 LOGV("w: %d\n", pix->width); 108 LOGV("h: %d\n", pix->height); 109 LOGV("color: %x\n", pix->colorspace); 110 111 switch (pix->pixelformat) { 112 case V4L2_PIX_FMT_YUYV: 113 LOGV("YUYV\n"); 114 break; 115 case V4L2_PIX_FMT_UYVY: 116 LOGV("UYVY\n"); 117 break; 118 case V4L2_PIX_FMT_RGB565: 119 LOGV("RGB565\n"); 120 break; 121 case V4L2_PIX_FMT_RGB565X: 122 LOGV("RGB565X\n"); 123 break; 124 default: 125 LOGV("not supported\n"); 126 } 127 } 128 129 void dump_crop(struct v4l2_crop *crop) 130 { 131 LOGV("crop l: %d ", crop->c.left); 132 LOGV("crop t: %d ", crop->c.top); 133 LOGV("crop w: %d ", crop->c.width); 134 LOGV("crop h: %d\n", crop->c.height); 135 } 136 137 void dump_window(struct v4l2_window *win) 138 { 139 LOGV("window l: %d ", win->w.left); 140 LOGV("window t: %d ", win->w.top); 141 LOGV("window w: %d ", win->w.width); 142 LOGV("window h: %d\n", win->w.height); 143 } 144 145 void v4l2_overlay_dump_state(int fd) 146 { 147 struct v4l2_format format; 148 struct v4l2_crop crop; 149 int ret; 150 151 LOGV("dumping driver state:"); 152 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 153 ret = ioctl(fd, VIDIOC_G_FMT, &format); 154 if (ret < 0) 155 return; 156 LOGV("output pixfmt:\n"); 157 dump_pixfmt(&format.fmt.pix); 158 159 format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 160 ret = ioctl(fd, VIDIOC_G_FMT, &format); 161 if (ret < 0) 162 return; 163 LOGV("v4l2_overlay window:\n"); 164 dump_window(&format.fmt.win); 165 166 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 167 ret = ioctl(fd, VIDIOC_G_CROP, &crop); 168 if (ret < 0) 169 return; 170 LOGV("output crop:\n"); 171 dump_crop(&crop); 172 } 173 174 static void error(int fd, const char *msg) 175 { 176 LOGE("Error = %s from %s", strerror(errno), msg); 177 #ifdef OVERLAY_DEBUG 178 v4l2_overlay_dump_state(fd); 179 #endif 180 } 181 182 static int v4l2_overlay_ioctl(int fd, int req, void *arg, const char* msg) 183 { 184 int ret; 185 ret = ioctl(fd, req, arg); 186 if (ret < 0) { 187 error(fd, msg); 188 return -1; 189 } 190 return 0; 191 } 192 193 #define v4l2_fourcc(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ 194 ((__u32)(c) << 16) | ((__u32)(d) << 24)) 195 /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ 196 #define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') 197 198 int configure_pixfmt(struct v4l2_pix_format *pix, int32_t fmt, 199 uint32_t w, uint32_t h) 200 { 201 LOG_FUNCTION_NAME 202 int fd; 203 204 switch (fmt) { 205 case OVERLAY_FORMAT_RGBA_8888: 206 return -1; 207 case OVERLAY_FORMAT_RGB_565: 208 pix->pixelformat = V4L2_PIX_FMT_RGB565; 209 break; 210 case OVERLAY_FORMAT_BGRA_8888: 211 return -1; 212 case OVERLAY_FORMAT_YCbYCr_422_I: 213 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: 214 pix->pixelformat = V4L2_PIX_FMT_YUYV; 215 break; 216 case OVERLAY_FORMAT_CbYCrY_422_I: 217 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: 218 pix->pixelformat = V4L2_PIX_FMT_UYVY; 219 break; 220 case HAL_PIXEL_FORMAT_YCbCr_420_P: 221 pix->pixelformat = V4L2_PIX_FMT_YUV420; 222 break; 223 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: 224 pix->pixelformat = V4L2_PIX_FMT_NV12T; 225 break; 226 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: 227 pix->pixelformat = V4L2_PIX_FMT_NV21; 228 break; 229 default: 230 return -1; 231 } 232 pix->width = w; 233 pix->height = h; 234 return 0; 235 } 236 237 static void configure_window(struct v4l2_window *win, int32_t w, 238 int32_t h, int32_t x, int32_t y) 239 { 240 LOG_FUNCTION_NAME 241 242 win->w.left = x; 243 win->w.top = y; 244 win->w.width = w; 245 win->w.height = h; 246 } 247 248 void get_window(struct v4l2_format *format, int32_t *x, 249 int32_t *y, int32_t *w, int32_t *h) 250 { 251 LOG_FUNCTION_NAME 252 253 *x = format->fmt.win.w.left; 254 *y = format->fmt.win.w.top; 255 *w = format->fmt.win.w.width; 256 *h = format->fmt.win.w.height; 257 } 258 259 int v4l2_overlay_init(int fd, uint32_t w, uint32_t h, uint32_t fmt, 260 uint32_t addr) 261 { 262 LOG_FUNCTION_NAME 263 264 struct v4l2_format format; 265 struct v4l2_framebuffer fbuf; 266 int ret; 267 268 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 269 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &format, "get format"); 270 if (ret) 271 return ret; 272 LOGV("v4l2_overlay_init:: w=%d h=%d\n", format.fmt.pix.width, 273 format.fmt.pix.height); 274 275 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 276 configure_pixfmt(&format.fmt.pix, fmt, w, h); 277 LOGV("v4l2_overlay_init:: w=%d h=%d\n", format.fmt.pix.width, 278 format.fmt.pix.height); 279 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FMT, &format, "set output format"); 280 if (ret) 281 return ret; 282 283 ret = v4l2_overlay_s_fbuf(fd, 0); 284 if (ret) 285 return ret; 286 287 return ret; 288 } 289 290 int v4l2_overlay_s_fbuf(int fd, int rotation) 291 { 292 struct v4l2_framebuffer fbuf; 293 int ret; 294 295 /* configure the v4l2_overlay framebuffer */ 296 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FBUF, &fbuf, "get fbuf"); 297 if (ret) 298 return ret; 299 300 /* if fbuf.base value is set by 0, using local DMA. */ 301 fbuf.base = (void *)0; 302 if (rotation == 0 || rotation == 180) { 303 fbuf.fmt.width = g_lcd_width; 304 fbuf.fmt.height = g_lcd_height; 305 } else { 306 fbuf.fmt.width = g_lcd_height; 307 fbuf.fmt.height = g_lcd_width; 308 } 309 310 if (g_lcd_bpp == 32) 311 fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB32; 312 else 313 fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565; 314 315 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FBUF, &fbuf, "set fbuf"); 316 if (ret) 317 return ret; 318 319 return ret; 320 } 321 322 int v4l2_overlay_get_input_size_and_format(int fd, uint32_t *w, uint32_t *h 323 , uint32_t *fmt) 324 { 325 LOG_FUNCTION_NAME 326 327 struct v4l2_format format; 328 int ret; 329 330 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 331 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &format, "get format"); 332 *w = format.fmt.pix.width; 333 *h = format.fmt.pix.height; 334 if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) 335 *fmt = OVERLAY_FORMAT_CbYCrY_422_I; 336 else 337 return -EINVAL; 338 return ret; 339 } 340 341 int v4l2_overlay_set_position(int fd, int32_t x, int32_t y 342 , int32_t w, int32_t h, int rotation) 343 { 344 LOG_FUNCTION_NAME 345 346 struct v4l2_format format; 347 int ret; 348 int rot_x = 0, rot_y = 0 , rot_w = 0, rot_h = 0; 349 350 /* configure the src format pix */ 351 /* configure the dst v4l2_overlay window */ 352 format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 353 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &format, 354 "get v4l2_overlay format"); 355 if (ret) 356 return ret; 357 LOGV("v4l2_overlay_set_position:: w=%d h=%d", format.fmt.win.w.width 358 , format.fmt.win.w.height); 359 360 if (rotation == 0) { 361 rot_x = x; 362 rot_y = y; 363 rot_w = w; 364 rot_h = h; 365 } else if (rotation == 90) { 366 rot_x = y; 367 rot_y = g_lcd_width - (x + w); 368 rot_w = h; 369 rot_h = w; 370 } else if (rotation == 180) { 371 rot_x = g_lcd_width - (x + w); 372 rot_y = g_lcd_height - (y + h); 373 rot_w = w; 374 rot_h = h; 375 } else if (rotation == 270) { 376 rot_x = g_lcd_height - (y + h); 377 rot_y = x; 378 rot_w = h; 379 rot_h = w; 380 } 381 382 configure_window(&format.fmt.win, rot_w, rot_h, rot_x, rot_y); 383 384 format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 385 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FMT, &format, 386 "set v4l2_overlay format"); 387 388 LOGV("v4l2_overlay_set_position:: w=%d h=%d rotation=%d" 389 , format.fmt.win.w.width, format.fmt.win.w.height, rotation); 390 391 if (ret) 392 return ret; 393 v4l2_overlay_dump_state(fd); 394 395 return 0; 396 } 397 398 int v4l2_overlay_get_position(int fd, int32_t *x, int32_t *y, int32_t *w, 399 int32_t *h) 400 { 401 struct v4l2_format format; 402 int ret; 403 404 format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 405 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &format, 406 "get v4l2_overlay format"); 407 408 if (ret) 409 return ret; 410 411 get_window(&format, x, y, w, h); 412 413 return 0; 414 } 415 416 int v4l2_overlay_set_crop(int fd, uint32_t x, uint32_t y, uint32_t w, 417 uint32_t h) 418 { 419 LOG_FUNCTION_NAME 420 421 struct v4l2_crop crop; 422 int ret; 423 424 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 425 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_CROP, &crop, "get crop"); 426 crop.c.left = x; 427 crop.c.top = y; 428 crop.c.width = w; 429 crop.c.height = h; 430 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 431 432 LOGV("%s:crop.c.left = %d\n", __func__, crop.c.left); 433 LOGV("%s:crop.c.top = %d\n", __func__, crop.c.top); 434 LOGV("%s:crop.c.width = %d\n", __func__, crop.c.width); 435 LOGV("%s:crop.c.height = %d\n", __func__, crop.c.height); 436 LOGV("%s:crop.type = 0x%x\n", __func__, crop.type); 437 438 return v4l2_overlay_ioctl(fd, VIDIOC_S_CROP, &crop, "set crop"); 439 } 440 441 int v4l2_overlay_get_crop(int fd, uint32_t *x, uint32_t *y, uint32_t *w, 442 uint32_t *h) 443 { 444 LOG_FUNCTION_NAME 445 446 struct v4l2_crop crop; 447 int ret; 448 449 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 450 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_CROP, &crop, "get crop"); 451 *x = crop.c.left; 452 *y = crop.c.top; 453 *w = crop.c.width; 454 *h = crop.c.height; 455 return ret; 456 } 457 458 int v4l2_overlay_set_flip(int fd, int flip) 459 { 460 LOG_FUNCTION_NAME 461 462 int ret; 463 struct v4l2_control ctrl_v; 464 struct v4l2_control ctrl_h; 465 466 switch (flip) { 467 case 0: 468 ctrl_v.value = 0; 469 ctrl_h.value = 0; 470 break; 471 case V4L2_CID_HFLIP: 472 ctrl_v.value = 0; 473 ctrl_h.value = 1; 474 break; 475 case V4L2_CID_VFLIP: 476 ctrl_v.value = 1; 477 ctrl_h.value = 0; 478 break; 479 default: 480 return -1; 481 } 482 483 ctrl_v.id = V4L2_CID_VFLIP; 484 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_CTRL, &ctrl_v, "set vflip"); 485 if (ret) return ret; 486 487 ctrl_h.id = V4L2_CID_HFLIP; 488 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_CTRL, &ctrl_h, "set hflip"); 489 return ret; 490 } 491 492 int v4l2_overlay_set_rotation(int fd, int degree, int step) 493 { 494 LOG_FUNCTION_NAME 495 496 int ret; 497 struct v4l2_control ctrl; 498 499 ctrl.id = V4L2_CID_PRIV_ROTATION; 500 ctrl.value = degree; 501 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_CTRL, &ctrl, "set rotation"); 502 503 return ret; 504 } 505 506 int v4l2_overlay_set_colorkey(int fd, int enable, int colorkey) 507 { 508 LOG_FUNCTION_NAME 509 510 int ret; 511 struct v4l2_framebuffer fbuf; 512 struct v4l2_format fmt; 513 514 memset(&fbuf, 0, sizeof(fbuf)); 515 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FBUF, &fbuf, 516 "get transparency enables"); 517 518 if (ret) 519 return ret; 520 521 if (enable) 522 fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; 523 else 524 fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; 525 526 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FBUF, &fbuf, "enable colorkey"); 527 528 if (ret) 529 return ret; 530 531 if (enable) { 532 memset(&fmt, 0, sizeof(fmt)); 533 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 534 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &fmt, "get colorkey"); 535 536 if (ret) 537 return ret; 538 539 fmt.fmt.win.chromakey = colorkey & 0xFFFFFF; 540 541 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FMT, &fmt, "set colorkey"); 542 } 543 544 return ret; 545 } 546 547 int v4l2_overlay_set_global_alpha(int fd, int enable, int alpha) 548 { 549 LOG_FUNCTION_NAME 550 551 int ret; 552 struct v4l2_framebuffer fbuf; 553 struct v4l2_format fmt; 554 555 memset(&fbuf, 0, sizeof(fbuf)); 556 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FBUF, &fbuf, 557 "get transparency enables"); 558 559 if (ret) 560 return ret; 561 562 if (enable) 563 fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; 564 else 565 fbuf.flags &= ~V4L2_FBUF_FLAG_GLOBAL_ALPHA; 566 567 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FBUF, &fbuf, "enable global alpha"); 568 569 if (ret) 570 return ret; 571 572 if (enable) { 573 memset(&fmt, 0, sizeof(fmt)); 574 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 575 ret = v4l2_overlay_ioctl(fd, VIDIOC_G_FMT, &fmt, "get global alpha"); 576 577 if (ret) 578 return ret; 579 580 fmt.fmt.win.global_alpha = alpha & 0xFF; 581 582 ret = v4l2_overlay_ioctl(fd, VIDIOC_S_FMT, &fmt, "set global alpha"); 583 } 584 585 return ret; 586 } 587 588 int v4l2_overlay_set_local_alpha(int fd, int enable) 589 { 590 int ret; 591 struct v4l2_framebuffer fbuf; 592 593 ret = 0; 594 595 return ret; 596 } 597 598 int v4l2_overlay_req_buf(int fd, uint32_t *num_bufs, int cacheable_buffers, int zerocopy) 599 { 600 struct v4l2_requestbuffers reqbuf; 601 int ret, i; 602 603 reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 604 605 if (zerocopy) 606 reqbuf.memory = V4L2_MEMORY_USERPTR; 607 else 608 reqbuf.memory = V4L2_MEMORY_MMAP; 609 reqbuf.count = *num_bufs; 610 611 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf); 612 if (ret < 0) { 613 error(fd, "reqbuf ioctl"); 614 return ret; 615 } 616 617 if (reqbuf.count > *num_bufs) { 618 error(fd, "Not enough buffer structs passed to get_buffers"); 619 return -ENOMEM; 620 } 621 *num_bufs = reqbuf.count; 622 623 return 0; 624 } 625 626 static int is_mmaped(struct v4l2_buffer *buf) 627 { 628 return buf->flags == V4L2_BUF_FLAG_MAPPED; 629 } 630 631 static int is_queued(struct v4l2_buffer *buf) 632 { 633 /* is either on the input or output queue in the kernel */ 634 return (buf->flags & V4L2_BUF_FLAG_QUEUED) || 635 (buf->flags & V4L2_BUF_FLAG_DONE); 636 } 637 638 static int is_dequeued(struct v4l2_buffer *buf) 639 { 640 /* is on neither input or output queue in kernel */ 641 return !(buf->flags & V4L2_BUF_FLAG_QUEUED) && 642 !(buf->flags & V4L2_BUF_FLAG_DONE); 643 } 644 645 int v4l2_overlay_query_buffer(int fd, int index, struct v4l2_buffer *buf) 646 { 647 LOG_FUNCTION_NAME 648 649 memset(buf, 0, sizeof(struct v4l2_buffer)); 650 651 buf->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 652 buf->memory = V4L2_MEMORY_MMAP; 653 buf->index = index; 654 LOGV("query buffer, mem=%u type=%u index=%u\n", 655 buf->memory, buf->type, buf->index); 656 return v4l2_overlay_ioctl(fd, VIDIOC_QUERYBUF, buf, "querybuf ioctl"); 657 } 658 659 int v4l2_overlay_map_buf(int fd, int index, void **start, size_t *len) 660 { 661 LOG_FUNCTION_NAME 662 663 struct v4l2_buffer buf; 664 int ret; 665 666 ret = v4l2_overlay_query_buffer(fd, index, &buf); 667 if (ret) 668 return ret; 669 670 if (is_mmaped(&buf)) { 671 LOGE("Trying to mmap buffers that are already mapped!\n"); 672 return -EINVAL; 673 } 674 675 *len = buf.length; 676 *start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, 677 fd, buf.m.offset); 678 if (*start == MAP_FAILED) { 679 LOGE("map failed, length=%u offset=%u\n", buf.length, buf.m.offset); 680 return -EINVAL; 681 } 682 return 0; 683 } 684 685 int v4l2_overlay_unmap_buf(void *start, size_t len) 686 { 687 LOG_FUNCTION_NAME 688 return munmap(start, len); 689 } 690 691 692 int v4l2_overlay_get_caps(int fd, struct v4l2_capability *caps) 693 { 694 return v4l2_overlay_ioctl(fd, VIDIOC_QUERYCAP, caps, "query cap"); 695 } 696 697 int v4l2_overlay_stream_on(int fd) 698 { 699 int ret; 700 uint32_t type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 701 702 ret = v4l2_overlay_set_local_alpha(fd, 1); 703 if (ret) 704 return ret; 705 706 ret = v4l2_overlay_ioctl(fd, VIDIOC_STREAMON, &type, "stream on"); 707 708 return ret; 709 } 710 711 int v4l2_overlay_stream_off(int fd) 712 { 713 int ret; 714 uint32_t type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 715 716 ret = v4l2_overlay_set_local_alpha(fd, 0); 717 if (ret) 718 return ret; 719 720 ret = v4l2_overlay_ioctl(fd, VIDIOC_STREAMOFF, &type, "stream off"); 721 722 return ret; 723 } 724 725 int v4l2_overlay_q_buf(int fd, int buffer, int zerocopy) 726 { 727 struct v4l2_buffer buf; 728 int ret; 729 730 if (zerocopy) { 731 uint8_t *pPhyYAddr; 732 uint8_t *pPhyCAddr; 733 struct fimc_buf fimc_src_buf; 734 uint8_t index; 735 736 memcpy(&pPhyYAddr, (void *) buffer, sizeof(pPhyYAddr)); 737 memcpy(&pPhyCAddr, (void *) (buffer + sizeof(pPhyYAddr)), 738 sizeof(pPhyCAddr)); 739 memcpy(&index, 740 (void *) (buffer + sizeof(pPhyYAddr) + sizeof(pPhyCAddr)), 741 sizeof(index)); 742 743 fimc_src_buf.base[0] = (dma_addr_t) pPhyYAddr; 744 fimc_src_buf.base[1] = (dma_addr_t) pPhyCAddr; 745 fimc_src_buf.base[2] = 746 (dma_addr_t) (pPhyCAddr + (pPhyCAddr - pPhyYAddr)/4); 747 748 buf.index = index; 749 buf.memory = V4L2_MEMORY_USERPTR; 750 buf.m.userptr = (unsigned long)&fimc_src_buf; 751 buf.length = 0; 752 } else { 753 buf.index = buffer; 754 buf.memory = V4L2_MEMORY_MMAP; 755 } 756 757 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 758 buf.field = V4L2_FIELD_NONE; 759 buf.timestamp.tv_sec = 0; 760 buf.timestamp.tv_usec = 0; 761 buf.flags = 0; 762 763 return v4l2_overlay_ioctl(fd, VIDIOC_QBUF, &buf, "qbuf"); 764 } 765 766 int v4l2_overlay_dq_buf(int fd, int *index, int zerocopy) 767 { 768 struct v4l2_buffer buf; 769 int ret; 770 771 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 772 773 if (zerocopy) 774 buf.memory = V4L2_MEMORY_USERPTR; 775 else 776 buf.memory = V4L2_MEMORY_MMAP; 777 778 ret = v4l2_overlay_ioctl(fd, VIDIOC_DQBUF, &buf, "dqbuf"); 779 if (ret) 780 return ret; 781 *index = buf.index; 782 return 0; 783 } 784