1 /* 2 * omap_vout.c 3 * 4 * Copyright (C) 2005-2010 Texas Instruments. 5 * 6 * This file is licensed under the terms of the GNU General Public License 7 * version 2. This program is licensed "as is" without any warranty of any 8 * kind, whether express or implied. 9 * 10 * Leveraged code from the OMAP2 camera driver 11 * Video-for-Linux (Version 2) camera capture driver for 12 * the OMAP24xx camera controller. 13 * 14 * Author: Andy Lowe (source@mvista.com) 15 * 16 * Copyright (C) 2004 MontaVista Software, Inc. 17 * Copyright (C) 2010 Texas Instruments. 18 * 19 * History: 20 * 20-APR-2006 Khasim Modified VRFB based Rotation, 21 * The image data is always read from 0 degree 22 * view and written 23 * to the virtual space of desired rotation angle 24 * 4-DEC-2006 Jian Changed to support better memory management 25 * 26 * 17-Nov-2008 Hardik Changed driver to use video_ioctl2 27 * 28 * 23-Feb-2010 Vaibhav H Modified to use new DSS2 interface 29 * 30 */ 31 32 #include <linux/init.h> 33 #include <linux/module.h> 34 #include <linux/vmalloc.h> 35 #include <linux/sched.h> 36 #include <linux/types.h> 37 #include <linux/platform_device.h> 38 #include <linux/irq.h> 39 #include <linux/videodev2.h> 40 #include <linux/dma-mapping.h> 41 #include <linux/slab.h> 42 43 #include <media/v4l2-device.h> 44 #include <media/v4l2-ioctl.h> 45 #include <media/v4l2-event.h> 46 47 #include <video/omapvrfb.h> 48 #include <video/omapfb_dss.h> 49 50 #include "omap_voutlib.h" 51 #include "omap_voutdef.h" 52 #include "omap_vout_vrfb.h" 53 54 MODULE_AUTHOR("Texas Instruments"); 55 MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); 56 MODULE_LICENSE("GPL"); 57 58 /* Driver Configuration macros */ 59 #define VOUT_NAME "omap_vout" 60 61 enum omap_vout_channels { 62 OMAP_VIDEO1, 63 OMAP_VIDEO2, 64 }; 65 66 /* Variables configurable through module params*/ 67 static bool vid1_static_vrfb_alloc; 68 static bool vid2_static_vrfb_alloc; 69 static bool debug; 70 71 /* Module parameters */ 72 module_param(vid1_static_vrfb_alloc, bool, S_IRUGO); 73 MODULE_PARM_DESC(vid1_static_vrfb_alloc, 74 "Static allocation of the VRFB buffer for video1 device"); 75 76 module_param(vid2_static_vrfb_alloc, bool, S_IRUGO); 77 MODULE_PARM_DESC(vid2_static_vrfb_alloc, 78 "Static allocation of the VRFB buffer for video2 device"); 79 80 module_param(debug, bool, S_IRUGO); 81 MODULE_PARM_DESC(debug, "Debug level (0-1)"); 82 83 /* list of image formats supported by OMAP2 video pipelines */ 84 static const struct v4l2_fmtdesc omap_formats[] = { 85 { 86 /* Note: V4L2 defines RGB565 as: 87 * 88 * Byte 0 Byte 1 89 * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 90 * 91 * We interpret RGB565 as: 92 * 93 * Byte 0 Byte 1 94 * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 95 */ 96 .pixelformat = V4L2_PIX_FMT_RGB565, 97 }, 98 { 99 /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use 100 * this for RGB24 unpack mode, the last 8 bits are ignored 101 * */ 102 .pixelformat = V4L2_PIX_FMT_RGB32, 103 }, 104 { 105 /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use 106 * this for RGB24 packed mode 107 * 108 */ 109 .pixelformat = V4L2_PIX_FMT_RGB24, 110 }, 111 { 112 .pixelformat = V4L2_PIX_FMT_YUYV, 113 }, 114 { 115 .pixelformat = V4L2_PIX_FMT_UYVY, 116 }, 117 }; 118 119 #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) 120 121 /* 122 * Try format 123 */ 124 static int omap_vout_try_format(struct v4l2_pix_format *pix) 125 { 126 int ifmt, bpp = 0; 127 128 pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT, 129 (u32)VID_MAX_HEIGHT); 130 pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH); 131 132 for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) { 133 if (pix->pixelformat == omap_formats[ifmt].pixelformat) 134 break; 135 } 136 137 if (ifmt == NUM_OUTPUT_FORMATS) 138 ifmt = 0; 139 140 pix->pixelformat = omap_formats[ifmt].pixelformat; 141 pix->field = V4L2_FIELD_NONE; 142 143 switch (pix->pixelformat) { 144 case V4L2_PIX_FMT_YUYV: 145 case V4L2_PIX_FMT_UYVY: 146 default: 147 pix->colorspace = V4L2_COLORSPACE_SRGB; 148 bpp = YUYV_BPP; 149 break; 150 case V4L2_PIX_FMT_RGB565: 151 case V4L2_PIX_FMT_RGB565X: 152 pix->colorspace = V4L2_COLORSPACE_SRGB; 153 bpp = RGB565_BPP; 154 break; 155 case V4L2_PIX_FMT_RGB24: 156 pix->colorspace = V4L2_COLORSPACE_SRGB; 157 bpp = RGB24_BPP; 158 break; 159 case V4L2_PIX_FMT_RGB32: 160 case V4L2_PIX_FMT_BGR32: 161 pix->colorspace = V4L2_COLORSPACE_SRGB; 162 bpp = RGB32_BPP; 163 break; 164 } 165 pix->bytesperline = pix->width * bpp; 166 pix->sizeimage = pix->bytesperline * pix->height; 167 168 return bpp; 169 } 170 171 /* 172 * Convert V4L2 rotation to DSS rotation 173 * V4L2 understand 0, 90, 180, 270. 174 * Convert to 0, 1, 2 and 3 respectively for DSS 175 */ 176 static int v4l2_rot_to_dss_rot(int v4l2_rotation, 177 enum dss_rotation *rotation, bool mirror) 178 { 179 int ret = 0; 180 181 switch (v4l2_rotation) { 182 case 90: 183 *rotation = dss_rotation_90_degree; 184 break; 185 case 180: 186 *rotation = dss_rotation_180_degree; 187 break; 188 case 270: 189 *rotation = dss_rotation_270_degree; 190 break; 191 case 0: 192 *rotation = dss_rotation_0_degree; 193 break; 194 default: 195 ret = -EINVAL; 196 } 197 return ret; 198 } 199 200 static int omap_vout_calculate_offset(struct omap_vout_device *vout) 201 { 202 struct omapvideo_info *ovid; 203 struct v4l2_rect *crop = &vout->crop; 204 struct v4l2_pix_format *pix = &vout->pix; 205 int *cropped_offset = &vout->cropped_offset; 206 int ps = 2, line_length = 0; 207 208 ovid = &vout->vid_info; 209 210 if (ovid->rotation_type == VOUT_ROT_VRFB) { 211 omap_vout_calculate_vrfb_offset(vout); 212 } else { 213 vout->line_length = line_length = pix->width; 214 215 if (V4L2_PIX_FMT_YUYV == pix->pixelformat || 216 V4L2_PIX_FMT_UYVY == pix->pixelformat) 217 ps = 2; 218 else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) 219 ps = 4; 220 else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) 221 ps = 3; 222 223 vout->ps = ps; 224 225 *cropped_offset = (line_length * ps) * 226 crop->top + crop->left * ps; 227 } 228 229 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", 230 __func__, vout->cropped_offset); 231 232 return 0; 233 } 234 235 /* 236 * Convert V4L2 pixel format to DSS pixel format 237 */ 238 static int video_mode_to_dss_mode(struct omap_vout_device *vout) 239 { 240 struct omap_overlay *ovl; 241 struct omapvideo_info *ovid; 242 struct v4l2_pix_format *pix = &vout->pix; 243 enum omap_color_mode mode; 244 245 ovid = &vout->vid_info; 246 ovl = ovid->overlays[0]; 247 248 switch (pix->pixelformat) { 249 case V4L2_PIX_FMT_YUYV: 250 mode = OMAP_DSS_COLOR_YUV2; 251 break; 252 case V4L2_PIX_FMT_UYVY: 253 mode = OMAP_DSS_COLOR_UYVY; 254 break; 255 case V4L2_PIX_FMT_RGB565: 256 mode = OMAP_DSS_COLOR_RGB16; 257 break; 258 case V4L2_PIX_FMT_RGB24: 259 mode = OMAP_DSS_COLOR_RGB24P; 260 break; 261 case V4L2_PIX_FMT_RGB32: 262 mode = (ovl->id == OMAP_DSS_VIDEO1) ? 263 OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32; 264 break; 265 case V4L2_PIX_FMT_BGR32: 266 mode = OMAP_DSS_COLOR_RGBX32; 267 break; 268 default: 269 mode = -EINVAL; 270 break; 271 } 272 return mode; 273 } 274 275 /* 276 * Setup the overlay 277 */ 278 static int omapvid_setup_overlay(struct omap_vout_device *vout, 279 struct omap_overlay *ovl, int posx, int posy, int outw, 280 int outh, dma_addr_t addr) 281 { 282 int ret = 0; 283 struct omap_overlay_info info; 284 int cropheight, cropwidth, pixwidth; 285 286 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 && 287 (outw != vout->pix.width || outh != vout->pix.height)) { 288 ret = -EINVAL; 289 goto setup_ovl_err; 290 } 291 292 vout->dss_mode = video_mode_to_dss_mode(vout); 293 if (vout->dss_mode == -EINVAL) { 294 ret = -EINVAL; 295 goto setup_ovl_err; 296 } 297 298 /* Setup the input plane parameters according to 299 * rotation value selected. 300 */ 301 if (is_rotation_90_or_270(vout)) { 302 cropheight = vout->crop.width; 303 cropwidth = vout->crop.height; 304 pixwidth = vout->pix.height; 305 } else { 306 cropheight = vout->crop.height; 307 cropwidth = vout->crop.width; 308 pixwidth = vout->pix.width; 309 } 310 311 ovl->get_overlay_info(ovl, &info); 312 info.paddr = addr; 313 info.width = cropwidth; 314 info.height = cropheight; 315 info.color_mode = vout->dss_mode; 316 info.mirror = vout->mirror; 317 info.pos_x = posx; 318 info.pos_y = posy; 319 info.out_width = outw; 320 info.out_height = outh; 321 info.global_alpha = vout->win.global_alpha; 322 if (!is_rotation_enabled(vout)) { 323 info.rotation = 0; 324 info.rotation_type = OMAP_DSS_ROT_DMA; 325 info.screen_width = pixwidth; 326 } else { 327 info.rotation = vout->rotation; 328 info.rotation_type = OMAP_DSS_ROT_VRFB; 329 info.screen_width = 2048; 330 } 331 332 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, 333 "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n" 334 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n" 335 "out_height=%d rotation_type=%d screen_width=%d\n", __func__, 336 ovl->is_enabled(ovl), &info.paddr, info.width, info.height, 337 info.color_mode, info.rotation, info.mirror, info.pos_x, 338 info.pos_y, info.out_width, info.out_height, info.rotation_type, 339 info.screen_width); 340 341 ret = ovl->set_overlay_info(ovl, &info); 342 if (ret) 343 goto setup_ovl_err; 344 345 return 0; 346 347 setup_ovl_err: 348 v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n"); 349 return ret; 350 } 351 352 /* 353 * Initialize the overlay structure 354 */ 355 static int omapvid_init(struct omap_vout_device *vout, dma_addr_t addr) 356 { 357 int ret = 0, i; 358 struct v4l2_window *win; 359 struct omap_overlay *ovl; 360 int posx, posy, outw, outh; 361 struct omap_video_timings *timing; 362 struct omapvideo_info *ovid = &vout->vid_info; 363 364 win = &vout->win; 365 for (i = 0; i < ovid->num_overlays; i++) { 366 struct omap_dss_device *dssdev; 367 368 ovl = ovid->overlays[i]; 369 dssdev = ovl->get_device(ovl); 370 371 if (!dssdev) 372 return -EINVAL; 373 374 timing = &dssdev->panel.timings; 375 376 outw = win->w.width; 377 outh = win->w.height; 378 switch (vout->rotation) { 379 case dss_rotation_90_degree: 380 /* Invert the height and width for 90 381 * and 270 degree rotation 382 */ 383 swap(outw, outh); 384 posy = (timing->y_res - win->w.width) - win->w.left; 385 posx = win->w.top; 386 break; 387 388 case dss_rotation_180_degree: 389 posx = (timing->x_res - win->w.width) - win->w.left; 390 posy = (timing->y_res - win->w.height) - win->w.top; 391 break; 392 393 case dss_rotation_270_degree: 394 swap(outw, outh); 395 posy = win->w.left; 396 posx = (timing->x_res - win->w.height) - win->w.top; 397 break; 398 399 default: 400 posx = win->w.left; 401 posy = win->w.top; 402 break; 403 } 404 405 ret = omapvid_setup_overlay(vout, ovl, posx, posy, 406 outw, outh, addr); 407 if (ret) 408 goto omapvid_init_err; 409 } 410 return 0; 411 412 omapvid_init_err: 413 v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n"); 414 return ret; 415 } 416 417 /* 418 * Apply the changes set the go bit of DSS 419 */ 420 static int omapvid_apply_changes(struct omap_vout_device *vout) 421 { 422 int i; 423 struct omap_overlay *ovl; 424 struct omapvideo_info *ovid = &vout->vid_info; 425 426 for (i = 0; i < ovid->num_overlays; i++) { 427 struct omap_dss_device *dssdev; 428 429 ovl = ovid->overlays[i]; 430 dssdev = ovl->get_device(ovl); 431 if (!dssdev) 432 return -EINVAL; 433 ovl->manager->apply(ovl->manager); 434 } 435 436 return 0; 437 } 438 439 static int omapvid_handle_interlace_display(struct omap_vout_device *vout, 440 unsigned int irqstatus, u64 ts) 441 { 442 u32 fid; 443 444 if (vout->first_int) { 445 vout->first_int = 0; 446 goto err; 447 } 448 449 if (irqstatus & DISPC_IRQ_EVSYNC_ODD) 450 fid = 1; 451 else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) 452 fid = 0; 453 else 454 goto err; 455 456 vout->field_id ^= 1; 457 if (fid != vout->field_id) { 458 if (fid == 0) 459 vout->field_id = fid; 460 } else if (0 == fid) { 461 if (vout->cur_frm == vout->next_frm) 462 goto err; 463 464 vout->cur_frm->vbuf.vb2_buf.timestamp = ts; 465 vout->cur_frm->vbuf.sequence = vout->sequence++; 466 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE); 467 vout->cur_frm = vout->next_frm; 468 } else { 469 if (list_empty(&vout->dma_queue) || 470 (vout->cur_frm != vout->next_frm)) 471 goto err; 472 } 473 474 return vout->field_id; 475 err: 476 return 0; 477 } 478 479 static void omap_vout_isr(void *arg, unsigned int irqstatus) 480 { 481 int ret, fid, mgr_id; 482 dma_addr_t addr; 483 u32 irq; 484 struct omap_overlay *ovl; 485 u64 ts; 486 struct omapvideo_info *ovid; 487 struct omap_dss_device *cur_display; 488 struct omap_vout_device *vout = (struct omap_vout_device *)arg; 489 490 ovid = &vout->vid_info; 491 ovl = ovid->overlays[0]; 492 493 mgr_id = ovl->manager->id; 494 495 /* get the display device attached to the overlay */ 496 cur_display = ovl->get_device(ovl); 497 498 if (!cur_display) 499 return; 500 501 spin_lock(&vout->vbq_lock); 502 ts = ktime_get_ns(); 503 504 switch (cur_display->type) { 505 case OMAP_DISPLAY_TYPE_DSI: 506 case OMAP_DISPLAY_TYPE_DPI: 507 case OMAP_DISPLAY_TYPE_DVI: 508 if (mgr_id == OMAP_DSS_CHANNEL_LCD) 509 irq = DISPC_IRQ_VSYNC; 510 else if (mgr_id == OMAP_DSS_CHANNEL_LCD2) 511 irq = DISPC_IRQ_VSYNC2; 512 else 513 goto vout_isr_err; 514 515 if (!(irqstatus & irq)) 516 goto vout_isr_err; 517 break; 518 case OMAP_DISPLAY_TYPE_VENC: 519 fid = omapvid_handle_interlace_display(vout, irqstatus, 520 ts); 521 if (!fid) 522 goto vout_isr_err; 523 break; 524 case OMAP_DISPLAY_TYPE_HDMI: 525 if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) 526 goto vout_isr_err; 527 break; 528 default: 529 goto vout_isr_err; 530 } 531 532 if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { 533 vout->cur_frm->vbuf.vb2_buf.timestamp = ts; 534 vout->cur_frm->vbuf.sequence = vout->sequence++; 535 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE); 536 vout->cur_frm = vout->next_frm; 537 } 538 539 vout->first_int = 0; 540 if (list_empty(&vout->dma_queue)) 541 goto vout_isr_err; 542 543 vout->next_frm = list_entry(vout->dma_queue.next, 544 struct omap_vout_buffer, queue); 545 list_del(&vout->next_frm->queue); 546 547 addr = vout->queued_buf_addr[vout->next_frm->vbuf.vb2_buf.index] 548 + vout->cropped_offset; 549 550 /* First save the configuration in ovelray structure */ 551 ret = omapvid_init(vout, addr); 552 if (ret) { 553 printk(KERN_ERR VOUT_NAME 554 "failed to set overlay info\n"); 555 goto vout_isr_err; 556 } 557 558 /* Enable the pipeline and set the Go bit */ 559 ret = omapvid_apply_changes(vout); 560 if (ret) 561 printk(KERN_ERR VOUT_NAME "failed to change mode\n"); 562 563 vout_isr_err: 564 spin_unlock(&vout->vbq_lock); 565 } 566 567 568 /* 569 * V4L2 ioctls 570 */ 571 static int vidioc_querycap(struct file *file, void *fh, 572 struct v4l2_capability *cap) 573 { 574 struct omap_vout_device *vout = video_drvdata(file); 575 576 strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); 577 strscpy(cap->card, vout->vfd->name, sizeof(cap->card)); 578 snprintf(cap->bus_info, sizeof(cap->bus_info), 579 "platform:%s.%d", VOUT_NAME, vout->vid); 580 return 0; 581 } 582 583 static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, 584 struct v4l2_fmtdesc *fmt) 585 { 586 int index = fmt->index; 587 588 if (index >= NUM_OUTPUT_FORMATS) 589 return -EINVAL; 590 591 fmt->flags = omap_formats[index].flags; 592 fmt->pixelformat = omap_formats[index].pixelformat; 593 594 return 0; 595 } 596 597 static int vidioc_g_fmt_vid_out(struct file *file, void *fh, 598 struct v4l2_format *f) 599 { 600 struct omap_vout_device *vout = video_drvdata(file); 601 602 f->fmt.pix = vout->pix; 603 return 0; 604 605 } 606 607 static int vidioc_try_fmt_vid_out(struct file *file, void *fh, 608 struct v4l2_format *f) 609 { 610 struct omap_overlay *ovl; 611 struct omapvideo_info *ovid; 612 struct omap_video_timings *timing; 613 struct omap_vout_device *vout = video_drvdata(file); 614 struct omap_dss_device *dssdev; 615 616 ovid = &vout->vid_info; 617 ovl = ovid->overlays[0]; 618 /* get the display device attached to the overlay */ 619 dssdev = ovl->get_device(ovl); 620 621 if (!dssdev) 622 return -EINVAL; 623 624 timing = &dssdev->panel.timings; 625 626 vout->fbuf.fmt.height = timing->y_res; 627 vout->fbuf.fmt.width = timing->x_res; 628 629 omap_vout_try_format(&f->fmt.pix); 630 return 0; 631 } 632 633 static int vidioc_s_fmt_vid_out(struct file *file, void *fh, 634 struct v4l2_format *f) 635 { 636 int ret, bpp; 637 struct omap_overlay *ovl; 638 struct omapvideo_info *ovid; 639 struct omap_video_timings *timing; 640 struct omap_vout_device *vout = video_drvdata(file); 641 struct omap_dss_device *dssdev; 642 643 if (vb2_is_busy(&vout->vq)) 644 return -EBUSY; 645 646 ovid = &vout->vid_info; 647 ovl = ovid->overlays[0]; 648 dssdev = ovl->get_device(ovl); 649 650 /* get the display device attached to the overlay */ 651 if (!dssdev) { 652 ret = -EINVAL; 653 goto s_fmt_vid_out_exit; 654 } 655 timing = &dssdev->panel.timings; 656 657 /* We don't support RGB24-packed mode if vrfb rotation 658 * is enabled*/ 659 if ((is_rotation_enabled(vout)) && 660 f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { 661 ret = -EINVAL; 662 goto s_fmt_vid_out_exit; 663 } 664 665 /* get the framebuffer parameters */ 666 667 if (is_rotation_90_or_270(vout)) { 668 vout->fbuf.fmt.height = timing->x_res; 669 vout->fbuf.fmt.width = timing->y_res; 670 } else { 671 vout->fbuf.fmt.height = timing->y_res; 672 vout->fbuf.fmt.width = timing->x_res; 673 } 674 675 /* change to smaller size is OK */ 676 677 bpp = omap_vout_try_format(&f->fmt.pix); 678 f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp; 679 680 /* try & set the new output format */ 681 vout->bpp = bpp; 682 vout->pix = f->fmt.pix; 683 vout->vrfb_bpp = 1; 684 685 /* If YUYV then vrfb bpp is 2, for others its 1 */ 686 if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || 687 V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) 688 vout->vrfb_bpp = 2; 689 690 /* set default crop and win */ 691 omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win); 692 693 ret = 0; 694 695 s_fmt_vid_out_exit: 696 return ret; 697 } 698 699 static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, 700 struct v4l2_format *f) 701 { 702 int ret = 0; 703 struct omap_vout_device *vout = video_drvdata(file); 704 struct omap_overlay *ovl; 705 struct omapvideo_info *ovid; 706 struct v4l2_window *win = &f->fmt.win; 707 708 ovid = &vout->vid_info; 709 ovl = ovid->overlays[0]; 710 711 ret = omap_vout_try_window(&vout->fbuf, win); 712 713 if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)) 714 win->global_alpha = 0; 715 716 return ret; 717 } 718 719 static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, 720 struct v4l2_format *f) 721 { 722 int ret = 0; 723 struct omap_overlay *ovl; 724 struct omapvideo_info *ovid; 725 struct omap_vout_device *vout = video_drvdata(file); 726 struct v4l2_window *win = &f->fmt.win; 727 728 ovid = &vout->vid_info; 729 ovl = ovid->overlays[0]; 730 731 ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); 732 if (!ret) { 733 enum omap_dss_trans_key_type key_type = 734 OMAP_DSS_COLOR_KEY_GFX_DST; 735 int enable; 736 737 /* Video1 plane does not support global alpha on OMAP3 */ 738 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) 739 vout->win.global_alpha = win->global_alpha; 740 else 741 win->global_alpha = 0; 742 if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY | 743 V4L2_FBUF_FLAG_SRC_CHROMAKEY)) 744 enable = 1; 745 else 746 enable = 0; 747 if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) 748 key_type = OMAP_DSS_COLOR_KEY_VID_SRC; 749 750 if (ovl->manager && ovl->manager->get_manager_info && 751 ovl->manager->set_manager_info) { 752 struct omap_overlay_manager_info info; 753 754 ovl->manager->get_manager_info(ovl->manager, &info); 755 info.trans_enabled = enable; 756 info.trans_key_type = key_type; 757 info.trans_key = vout->win.chromakey; 758 759 if (ovl->manager->set_manager_info(ovl->manager, &info)) 760 return -EINVAL; 761 } 762 } 763 return ret; 764 } 765 766 static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, 767 struct v4l2_format *f) 768 { 769 struct omap_overlay *ovl; 770 struct omapvideo_info *ovid; 771 struct omap_vout_device *vout = video_drvdata(file); 772 struct v4l2_window *win = &f->fmt.win; 773 774 ovid = &vout->vid_info; 775 ovl = ovid->overlays[0]; 776 777 win->w = vout->win.w; 778 win->field = vout->win.field; 779 win->chromakey = vout->win.chromakey; 780 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) 781 win->global_alpha = vout->win.global_alpha; 782 else 783 win->global_alpha = 0; 784 win->clips = NULL; 785 win->clipcount = 0; 786 win->bitmap = NULL; 787 return 0; 788 } 789 790 static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) 791 { 792 struct omap_vout_device *vout = video_drvdata(file); 793 struct v4l2_pix_format *pix = &vout->pix; 794 795 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 796 return -EINVAL; 797 798 switch (sel->target) { 799 case V4L2_SEL_TGT_CROP: 800 sel->r = vout->crop; 801 break; 802 case V4L2_SEL_TGT_CROP_DEFAULT: 803 omap_vout_default_crop(&vout->pix, &vout->fbuf, &sel->r); 804 break; 805 case V4L2_SEL_TGT_CROP_BOUNDS: 806 /* Width and height are always even */ 807 sel->r.width = pix->width & ~1; 808 sel->r.height = pix->height & ~1; 809 break; 810 default: 811 return -EINVAL; 812 } 813 return 0; 814 } 815 816 static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel) 817 { 818 int ret = -EINVAL; 819 struct omap_vout_device *vout = video_drvdata(file); 820 struct omapvideo_info *ovid; 821 struct omap_overlay *ovl; 822 struct omap_video_timings *timing; 823 struct omap_dss_device *dssdev; 824 825 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 826 return -EINVAL; 827 828 if (sel->target != V4L2_SEL_TGT_CROP) 829 return -EINVAL; 830 831 if (vb2_is_busy(&vout->vq)) 832 return -EBUSY; 833 834 ovid = &vout->vid_info; 835 ovl = ovid->overlays[0]; 836 /* get the display device attached to the overlay */ 837 dssdev = ovl->get_device(ovl); 838 839 if (!dssdev) { 840 ret = -EINVAL; 841 goto s_crop_err; 842 } 843 844 timing = &dssdev->panel.timings; 845 846 if (is_rotation_90_or_270(vout)) { 847 vout->fbuf.fmt.height = timing->x_res; 848 vout->fbuf.fmt.width = timing->y_res; 849 } else { 850 vout->fbuf.fmt.height = timing->y_res; 851 vout->fbuf.fmt.width = timing->x_res; 852 } 853 854 ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win, 855 &vout->fbuf, &sel->r); 856 857 s_crop_err: 858 return ret; 859 } 860 861 static int omap_vout_s_ctrl(struct v4l2_ctrl *ctrl) 862 { 863 struct omap_vout_device *vout = 864 container_of(ctrl->handler, struct omap_vout_device, ctrl_handler); 865 int ret = 0; 866 867 switch (ctrl->id) { 868 case V4L2_CID_ROTATE: { 869 struct omapvideo_info *ovid; 870 int rotation = ctrl->val; 871 872 ovid = &vout->vid_info; 873 874 if (rotation && ovid->rotation_type == VOUT_ROT_NONE) { 875 ret = -ERANGE; 876 break; 877 } 878 879 if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 880 ret = -EINVAL; 881 break; 882 } 883 884 if (v4l2_rot_to_dss_rot(rotation, &vout->rotation, 885 vout->mirror)) { 886 ret = -EINVAL; 887 break; 888 } 889 break; 890 } 891 case V4L2_CID_BG_COLOR: 892 { 893 struct omap_overlay *ovl; 894 unsigned int color = ctrl->val; 895 struct omap_overlay_manager_info info; 896 897 ovl = vout->vid_info.overlays[0]; 898 899 if (!ovl->manager || !ovl->manager->get_manager_info) { 900 ret = -EINVAL; 901 break; 902 } 903 904 ovl->manager->get_manager_info(ovl->manager, &info); 905 info.default_color = color; 906 if (ovl->manager->set_manager_info(ovl->manager, &info)) { 907 ret = -EINVAL; 908 break; 909 } 910 break; 911 } 912 case V4L2_CID_VFLIP: 913 { 914 struct omapvideo_info *ovid; 915 unsigned int mirror = ctrl->val; 916 917 ovid = &vout->vid_info; 918 919 if (mirror && ovid->rotation_type == VOUT_ROT_NONE) { 920 ret = -ERANGE; 921 break; 922 } 923 924 if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 925 ret = -EINVAL; 926 break; 927 } 928 vout->mirror = mirror; 929 break; 930 } 931 default: 932 return -EINVAL; 933 } 934 return ret; 935 } 936 937 static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = { 938 .s_ctrl = omap_vout_s_ctrl, 939 }; 940 941 static int omap_vout_vb2_queue_setup(struct vb2_queue *vq, 942 unsigned int *nbufs, 943 unsigned int *num_planes, unsigned int sizes[], 944 struct device *alloc_devs[]) 945 { 946 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 947 unsigned int q_num_bufs = vb2_get_num_buffers(vq); 948 int size = vout->pix.sizeimage; 949 950 if (is_rotation_enabled(vout) && q_num_bufs + *nbufs > VRFB_NUM_BUFS) { 951 *nbufs = VRFB_NUM_BUFS - q_num_bufs; 952 if (*nbufs == 0) 953 return -EINVAL; 954 } 955 956 if (*num_planes) 957 return sizes[0] < size ? -EINVAL : 0; 958 959 *num_planes = 1; 960 sizes[0] = size; 961 return 0; 962 } 963 964 static int omap_vout_vb2_prepare(struct vb2_buffer *vb) 965 { 966 struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue); 967 struct omapvideo_info *ovid = &vout->vid_info; 968 struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb); 969 dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 970 971 if (vb2_plane_size(vb, 0) < vout->pix.sizeimage) { 972 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, 973 "%s data will not fit into plane (%lu < %u)\n", 974 __func__, vb2_plane_size(vb, 0), vout->pix.sizeimage); 975 return -EINVAL; 976 } 977 978 vb2_set_plane_payload(vb, 0, vout->pix.sizeimage); 979 voutbuf->vbuf.field = V4L2_FIELD_NONE; 980 981 vout->queued_buf_addr[vb->index] = buf_phy_addr; 982 if (ovid->rotation_type == VOUT_ROT_VRFB) 983 return omap_vout_prepare_vrfb(vout, vb); 984 return 0; 985 } 986 987 static void omap_vout_vb2_queue(struct vb2_buffer *vb) 988 { 989 struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue); 990 struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb); 991 992 list_add_tail(&voutbuf->queue, &vout->dma_queue); 993 } 994 995 static int omap_vout_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) 996 { 997 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 998 struct omapvideo_info *ovid = &vout->vid_info; 999 struct omap_vout_buffer *buf, *tmp; 1000 dma_addr_t addr = 0; 1001 u32 mask = 0; 1002 int ret, j; 1003 1004 /* Get the next frame from the buffer queue */ 1005 vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next, 1006 struct omap_vout_buffer, queue); 1007 /* Remove buffer from the buffer queue */ 1008 list_del(&vout->cur_frm->queue); 1009 /* Initialize field_id and started member */ 1010 vout->field_id = 0; 1011 vout->first_int = 1; 1012 vout->sequence = 0; 1013 1014 if (omap_vout_calculate_offset(vout)) { 1015 ret = -EINVAL; 1016 goto out; 1017 } 1018 if (ovid->rotation_type == VOUT_ROT_VRFB) 1019 if (omap_vout_vrfb_buffer_setup(vout, &count, 0)) { 1020 ret = -ENOMEM; 1021 goto out; 1022 } 1023 1024 addr = vout->queued_buf_addr[vout->cur_frm->vbuf.vb2_buf.index] 1025 + vout->cropped_offset; 1026 1027 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1028 | DISPC_IRQ_VSYNC2; 1029 1030 /* First save the configuration in overlay structure */ 1031 ret = omapvid_init(vout, addr); 1032 if (ret) { 1033 v4l2_err(&vout->vid_dev->v4l2_dev, 1034 "failed to set overlay info\n"); 1035 goto streamon_err1; 1036 } 1037 1038 omap_dispc_register_isr(omap_vout_isr, vout, mask); 1039 1040 /* Enable the pipeline and set the Go bit */ 1041 ret = omapvid_apply_changes(vout); 1042 if (ret) 1043 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); 1044 1045 for (j = 0; j < ovid->num_overlays; j++) { 1046 struct omap_overlay *ovl = ovid->overlays[j]; 1047 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1048 1049 if (dssdev) { 1050 ret = ovl->enable(ovl); 1051 if (ret) 1052 goto streamon_err1; 1053 } 1054 } 1055 return 0; 1056 1057 streamon_err1: 1058 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1059 | DISPC_IRQ_VSYNC2; 1060 1061 omap_dispc_unregister_isr(omap_vout_isr, vout, mask); 1062 1063 for (j = 0; j < ovid->num_overlays; j++) { 1064 struct omap_overlay *ovl = ovid->overlays[j]; 1065 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1066 1067 if (dssdev) 1068 ovl->disable(ovl); 1069 } 1070 /* Turn of the pipeline */ 1071 if (omapvid_apply_changes(vout)) 1072 v4l2_err(&vout->vid_dev->v4l2_dev, 1073 "failed to change mode in streamoff\n"); 1074 1075 out: 1076 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); 1077 list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) { 1078 list_del(&buf->queue); 1079 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); 1080 } 1081 return ret; 1082 } 1083 1084 static void omap_vout_vb2_stop_streaming(struct vb2_queue *vq) 1085 { 1086 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 1087 struct omapvideo_info *ovid = &vout->vid_info; 1088 struct omap_vout_buffer *buf, *tmp; 1089 u32 mask = 0; 1090 int j; 1091 1092 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1093 | DISPC_IRQ_VSYNC2; 1094 1095 omap_dispc_unregister_isr(omap_vout_isr, vout, mask); 1096 1097 for (j = 0; j < ovid->num_overlays; j++) { 1098 struct omap_overlay *ovl = ovid->overlays[j]; 1099 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1100 1101 if (dssdev) 1102 ovl->disable(ovl); 1103 } 1104 /* Turn of the pipeline */ 1105 if (omapvid_apply_changes(vout)) 1106 v4l2_err(&vout->vid_dev->v4l2_dev, 1107 "failed to change mode in streamoff\n"); 1108 1109 if (vout->next_frm != vout->cur_frm) 1110 vb2_buffer_done(&vout->next_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1111 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1112 list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) { 1113 list_del(&buf->queue); 1114 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1115 } 1116 } 1117 1118 static int vidioc_s_fbuf(struct file *file, void *fh, 1119 const struct v4l2_framebuffer *a) 1120 { 1121 int enable = 0; 1122 struct omap_overlay *ovl; 1123 struct omapvideo_info *ovid; 1124 struct omap_vout_device *vout = video_drvdata(file); 1125 struct omap_overlay_manager_info info; 1126 enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 1127 1128 ovid = &vout->vid_info; 1129 ovl = ovid->overlays[0]; 1130 1131 /* OMAP DSS doesn't support Source and Destination color 1132 key together */ 1133 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && 1134 (a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) 1135 return -EINVAL; 1136 /* OMAP DSS Doesn't support the Destination color key 1137 and alpha blending together */ 1138 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) && 1139 (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA)) 1140 return -EINVAL; 1141 1142 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) { 1143 vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1144 key_type = OMAP_DSS_COLOR_KEY_VID_SRC; 1145 } else 1146 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1147 1148 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) { 1149 vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; 1150 key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 1151 } else 1152 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; 1153 1154 if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY | 1155 V4L2_FBUF_FLAG_SRC_CHROMAKEY)) 1156 enable = 1; 1157 else 1158 enable = 0; 1159 if (ovl->manager && ovl->manager->get_manager_info && 1160 ovl->manager->set_manager_info) { 1161 1162 ovl->manager->get_manager_info(ovl->manager, &info); 1163 info.trans_enabled = enable; 1164 info.trans_key_type = key_type; 1165 info.trans_key = vout->win.chromakey; 1166 1167 if (ovl->manager->set_manager_info(ovl->manager, &info)) 1168 return -EINVAL; 1169 } 1170 if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) { 1171 vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; 1172 enable = 1; 1173 } else { 1174 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA; 1175 enable = 0; 1176 } 1177 if (ovl->manager && ovl->manager->get_manager_info && 1178 ovl->manager->set_manager_info) { 1179 ovl->manager->get_manager_info(ovl->manager, &info); 1180 /* enable this only if there is no zorder cap */ 1181 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) 1182 info.partial_alpha_enabled = enable; 1183 if (ovl->manager->set_manager_info(ovl->manager, &info)) 1184 return -EINVAL; 1185 } 1186 1187 return 0; 1188 } 1189 1190 static int vidioc_g_fbuf(struct file *file, void *fh, 1191 struct v4l2_framebuffer *a) 1192 { 1193 struct omap_overlay *ovl; 1194 struct omapvideo_info *ovid; 1195 struct omap_vout_device *vout = video_drvdata(file); 1196 struct omap_overlay_manager_info info; 1197 struct omap_video_timings *timing; 1198 struct omap_dss_device *dssdev; 1199 1200 ovid = &vout->vid_info; 1201 ovl = ovid->overlays[0]; 1202 /* get the display device attached to the overlay */ 1203 dssdev = ovl->get_device(ovl); 1204 1205 if (!dssdev) 1206 return -EINVAL; 1207 1208 timing = &dssdev->panel.timings; 1209 1210 vout->fbuf.fmt.height = timing->y_res; 1211 vout->fbuf.fmt.width = timing->x_res; 1212 a->fmt.field = V4L2_FIELD_NONE; 1213 a->fmt.colorspace = V4L2_COLORSPACE_SRGB; 1214 a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32; 1215 a->fmt.height = vout->fbuf.fmt.height; 1216 a->fmt.width = vout->fbuf.fmt.width; 1217 a->fmt.bytesperline = vout->fbuf.fmt.width * 4; 1218 a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline; 1219 a->base = vout->fbuf.base; 1220 1221 a->flags = vout->fbuf.flags; 1222 a->capability = vout->fbuf.capability; 1223 a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY | 1224 V4L2_FBUF_FLAG_LOCAL_ALPHA); 1225 1226 if (ovl->manager && ovl->manager->get_manager_info) { 1227 ovl->manager->get_manager_info(ovl->manager, &info); 1228 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC) 1229 a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1230 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST) 1231 a->flags |= V4L2_FBUF_FLAG_CHROMAKEY; 1232 if (info.partial_alpha_enabled) 1233 a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; 1234 } 1235 1236 return 0; 1237 } 1238 1239 static int vidioc_enum_output(struct file *file, void *priv_fh, 1240 struct v4l2_output *out) 1241 { 1242 if (out->index) 1243 return -EINVAL; 1244 snprintf(out->name, sizeof(out->name), "Overlay"); 1245 out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; 1246 return 0; 1247 } 1248 1249 static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i) 1250 { 1251 *i = 0; 1252 return 0; 1253 } 1254 1255 static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i) 1256 { 1257 return i ? -EINVAL : 0; 1258 } 1259 1260 static const struct v4l2_ioctl_ops vout_ioctl_ops = { 1261 .vidioc_querycap = vidioc_querycap, 1262 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, 1263 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, 1264 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, 1265 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, 1266 .vidioc_s_fbuf = vidioc_s_fbuf, 1267 .vidioc_g_fbuf = vidioc_g_fbuf, 1268 .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_overlay, 1269 .vidioc_s_fmt_vid_out_overlay = vidioc_s_fmt_vid_overlay, 1270 .vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_overlay, 1271 .vidioc_g_selection = vidioc_g_selection, 1272 .vidioc_s_selection = vidioc_s_selection, 1273 .vidioc_enum_output = vidioc_enum_output, 1274 .vidioc_g_output = vidioc_g_output, 1275 .vidioc_s_output = vidioc_s_output, 1276 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1277 .vidioc_create_bufs = vb2_ioctl_create_bufs, 1278 .vidioc_querybuf = vb2_ioctl_querybuf, 1279 .vidioc_qbuf = vb2_ioctl_qbuf, 1280 .vidioc_dqbuf = vb2_ioctl_dqbuf, 1281 .vidioc_expbuf = vb2_ioctl_expbuf, 1282 .vidioc_streamon = vb2_ioctl_streamon, 1283 .vidioc_streamoff = vb2_ioctl_streamoff, 1284 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1285 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1286 }; 1287 1288 static const struct v4l2_file_operations omap_vout_fops = { 1289 .owner = THIS_MODULE, 1290 .unlocked_ioctl = video_ioctl2, 1291 .poll = vb2_fop_poll, 1292 .mmap = vb2_fop_mmap, 1293 .open = v4l2_fh_open, 1294 .release = vb2_fop_release, 1295 }; 1296 1297 static const struct vb2_ops omap_vout_vb2_ops = { 1298 .queue_setup = omap_vout_vb2_queue_setup, 1299 .buf_queue = omap_vout_vb2_queue, 1300 .buf_prepare = omap_vout_vb2_prepare, 1301 .start_streaming = omap_vout_vb2_start_streaming, 1302 .stop_streaming = omap_vout_vb2_stop_streaming, 1303 .wait_prepare = vb2_ops_wait_prepare, 1304 .wait_finish = vb2_ops_wait_finish, 1305 }; 1306 1307 /* Init functions used during driver initialization */ 1308 /* Initial setup of video_data */ 1309 static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) 1310 { 1311 struct video_device *vfd; 1312 struct v4l2_pix_format *pix; 1313 struct omap_overlay *ovl = vout->vid_info.overlays[0]; 1314 struct omap_dss_device *display = ovl->get_device(ovl); 1315 struct v4l2_ctrl_handler *hdl; 1316 struct vb2_queue *vq; 1317 int ret; 1318 1319 /* set the default pix */ 1320 pix = &vout->pix; 1321 1322 /* Set the default picture of QVGA */ 1323 pix->width = QQVGA_WIDTH; 1324 pix->height = QQVGA_HEIGHT; 1325 1326 /* Default pixel format is RGB 5-6-5 */ 1327 pix->pixelformat = V4L2_PIX_FMT_RGB565; 1328 pix->field = V4L2_FIELD_NONE; 1329 pix->bytesperline = pix->width * 2; 1330 pix->sizeimage = pix->bytesperline * pix->height; 1331 pix->colorspace = V4L2_COLORSPACE_SRGB; 1332 1333 vout->bpp = RGB565_BPP; 1334 vout->fbuf.fmt.width = display->panel.timings.x_res; 1335 vout->fbuf.fmt.height = display->panel.timings.y_res; 1336 vout->cropped_offset = 0; 1337 1338 /* Set the data structures for the overlay parameters*/ 1339 vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY; 1340 vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA | 1341 V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY | 1342 V4L2_FBUF_CAP_EXTERNOVERLAY; 1343 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) { 1344 vout->win.global_alpha = 255; 1345 vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA; 1346 vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; 1347 } else { 1348 vout->win.global_alpha = 0; 1349 } 1350 vout->win.field = V4L2_FIELD_NONE; 1351 1352 omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win); 1353 1354 hdl = &vout->ctrl_handler; 1355 v4l2_ctrl_handler_init(hdl, 3); 1356 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) { 1357 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1358 V4L2_CID_ROTATE, 0, 270, 90, 0); 1359 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1360 V4L2_CID_VFLIP, 0, 1, 1, 0); 1361 } 1362 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1363 V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0); 1364 if (hdl->error) 1365 return hdl->error; 1366 1367 vout->rotation = 0; 1368 vout->mirror = false; 1369 INIT_LIST_HEAD(&vout->dma_queue); 1370 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) 1371 vout->vrfb_bpp = 2; 1372 1373 /* initialize the video_device struct */ 1374 vfd = vout->vfd = video_device_alloc(); 1375 1376 if (!vfd) { 1377 printk(KERN_ERR VOUT_NAME 1378 ": could not allocate video device struct\n"); 1379 v4l2_ctrl_handler_free(hdl); 1380 return -ENOMEM; 1381 } 1382 vfd->ctrl_handler = hdl; 1383 vfd->release = video_device_release; 1384 vfd->ioctl_ops = &vout_ioctl_ops; 1385 1386 strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); 1387 1388 vfd->fops = &omap_vout_fops; 1389 vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; 1390 vfd->vfl_dir = VFL_DIR_TX; 1391 vfd->minor = -1; 1392 vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | 1393 V4L2_CAP_VIDEO_OUTPUT_OVERLAY; 1394 mutex_init(&vout->lock); 1395 1396 vq = &vout->vq; 1397 vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 1398 vq->io_modes = VB2_MMAP | VB2_DMABUF; 1399 vq->drv_priv = vout; 1400 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1401 vq->buf_struct_size = sizeof(struct omap_vout_buffer); 1402 vq->dev = vfd->v4l2_dev->dev; 1403 1404 vq->ops = &omap_vout_vb2_ops; 1405 vq->mem_ops = &vb2_dma_contig_memops; 1406 vq->lock = &vout->lock; 1407 vq->min_queued_buffers = 1; 1408 vfd->queue = vq; 1409 1410 ret = vb2_queue_init(vq); 1411 if (ret) { 1412 v4l2_ctrl_handler_free(hdl); 1413 video_device_release(vfd); 1414 } 1415 return ret; 1416 } 1417 1418 /* Setup video buffers */ 1419 static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, 1420 int vid_num) 1421 { 1422 struct omapvideo_info *ovid; 1423 struct omap_vout_device *vout; 1424 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1425 struct omap2video_device *vid_dev = 1426 container_of(v4l2_dev, struct omap2video_device, v4l2_dev); 1427 int ret = 0; 1428 1429 vout = vid_dev->vouts[vid_num]; 1430 ovid = &vout->vid_info; 1431 1432 if (ovid->rotation_type == VOUT_ROT_VRFB) { 1433 bool static_vrfb_allocation = (vid_num == 0) ? 1434 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; 1435 ret = omap_vout_setup_vrfb_bufs(pdev, vid_num, 1436 static_vrfb_allocation); 1437 } 1438 return ret; 1439 } 1440 1441 /* Create video out devices */ 1442 static int __init omap_vout_create_video_devices(struct platform_device *pdev) 1443 { 1444 int ret = 0, k; 1445 struct omap_vout_device *vout; 1446 struct video_device *vfd = NULL; 1447 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1448 struct omap2video_device *vid_dev = container_of(v4l2_dev, 1449 struct omap2video_device, v4l2_dev); 1450 struct omap_overlay *ovl = vid_dev->overlays[0]; 1451 struct omap_overlay_info info; 1452 1453 ovl->get_overlay_info(ovl, &info); 1454 1455 for (k = 0; k < pdev->num_resources; k++) { 1456 1457 vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL); 1458 if (!vout) { 1459 dev_err(&pdev->dev, ": could not allocate memory\n"); 1460 return -ENOMEM; 1461 } 1462 1463 vout->vid = k; 1464 vid_dev->vouts[k] = vout; 1465 vout->vid_dev = vid_dev; 1466 /* Select video2 if only 1 overlay is controlled by V4L2 */ 1467 if (pdev->num_resources == 1) 1468 vout->vid_info.overlays[0] = vid_dev->overlays[k + 2]; 1469 else 1470 /* Else select video1 and video2 one by one. */ 1471 vout->vid_info.overlays[0] = vid_dev->overlays[k + 1]; 1472 vout->vid_info.num_overlays = 1; 1473 vout->vid_info.id = k + 1; 1474 spin_lock_init(&vout->vbq_lock); 1475 /* 1476 * Set the framebuffer base, this allows applications to find 1477 * the fb corresponding to this overlay. 1478 * 1479 * To be precise: fbuf.base should match smem_start of 1480 * struct fb_fix_screeninfo. 1481 */ 1482 vout->fbuf.base = (void *)(uintptr_t)info.paddr; 1483 1484 /* Set VRFB as rotation_type for omap2 and omap3 */ 1485 if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx()) 1486 vout->vid_info.rotation_type = VOUT_ROT_VRFB; 1487 1488 /* Setup the default configuration for the video devices 1489 */ 1490 if (omap_vout_setup_video_data(vout) != 0) { 1491 ret = -ENOMEM; 1492 goto error; 1493 } 1494 1495 /* Allocate default number of buffers for the video streaming 1496 * and reserve the VRFB space for rotation 1497 */ 1498 if (omap_vout_setup_video_bufs(pdev, k) != 0) { 1499 ret = -ENOMEM; 1500 goto error1; 1501 } 1502 1503 /* Register the Video device with V4L2 1504 */ 1505 vfd = vout->vfd; 1506 if (video_register_device(vfd, VFL_TYPE_VIDEO, -1) < 0) { 1507 dev_err(&pdev->dev, 1508 ": Could not register Video for Linux device\n"); 1509 vfd->minor = -1; 1510 ret = -ENODEV; 1511 goto error2; 1512 } 1513 video_set_drvdata(vfd, vout); 1514 1515 dev_info(&pdev->dev, 1516 ": registered and initialized video device %d\n", 1517 vfd->minor); 1518 if (k == (pdev->num_resources - 1)) 1519 return 0; 1520 1521 continue; 1522 error2: 1523 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) 1524 omap_vout_release_vrfb(vout); 1525 error1: 1526 video_device_release(vfd); 1527 error: 1528 kfree(vout); 1529 return ret; 1530 } 1531 1532 return -ENODEV; 1533 } 1534 /* Driver functions */ 1535 static void omap_vout_cleanup_device(struct omap_vout_device *vout) 1536 { 1537 struct video_device *vfd; 1538 struct omapvideo_info *ovid; 1539 1540 if (!vout) 1541 return; 1542 1543 vfd = vout->vfd; 1544 ovid = &vout->vid_info; 1545 if (vfd) { 1546 if (!video_is_registered(vfd)) { 1547 /* 1548 * The device was never registered, so release the 1549 * video_device struct directly. 1550 */ 1551 video_device_release(vfd); 1552 } else { 1553 /* 1554 * The unregister function will release the video_device 1555 * struct as well as unregistering it. 1556 */ 1557 video_unregister_device(vfd); 1558 } 1559 } 1560 v4l2_ctrl_handler_free(&vout->ctrl_handler); 1561 if (ovid->rotation_type == VOUT_ROT_VRFB) { 1562 omap_vout_release_vrfb(vout); 1563 /* Free the VRFB buffer if allocated 1564 * init time 1565 */ 1566 if (vout->vrfb_static_allocation) 1567 omap_vout_free_vrfb_buffers(vout); 1568 } 1569 1570 kfree(vout); 1571 } 1572 1573 static void omap_vout_remove(struct platform_device *pdev) 1574 { 1575 int k; 1576 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1577 struct omap2video_device *vid_dev = container_of(v4l2_dev, struct 1578 omap2video_device, v4l2_dev); 1579 1580 v4l2_device_unregister(v4l2_dev); 1581 for (k = 0; k < pdev->num_resources; k++) 1582 omap_vout_cleanup_device(vid_dev->vouts[k]); 1583 1584 for (k = 0; k < vid_dev->num_displays; k++) { 1585 if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) 1586 vid_dev->displays[k]->driver->disable(vid_dev->displays[k]); 1587 1588 omap_dss_put_device(vid_dev->displays[k]); 1589 } 1590 kfree(vid_dev); 1591 } 1592 1593 static int __init omap_vout_probe(struct platform_device *pdev) 1594 { 1595 int ret = 0, i; 1596 struct omap_overlay *ovl; 1597 struct omap_dss_device *dssdev = NULL; 1598 struct omap_dss_device *def_display; 1599 struct omap2video_device *vid_dev = NULL; 1600 1601 if (omapdss_is_initialized() == false) 1602 return -EPROBE_DEFER; 1603 1604 ret = omapdss_compat_init(); 1605 if (ret) { 1606 dev_err(&pdev->dev, "failed to init dss\n"); 1607 return ret; 1608 } 1609 1610 if (pdev->num_resources == 0) { 1611 dev_err(&pdev->dev, "probed for an unknown device\n"); 1612 ret = -ENODEV; 1613 goto err_dss_init; 1614 } 1615 1616 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); 1617 if (vid_dev == NULL) { 1618 ret = -ENOMEM; 1619 goto err_dss_init; 1620 } 1621 1622 vid_dev->num_displays = 0; 1623 for_each_dss_dev(dssdev) { 1624 omap_dss_get_device(dssdev); 1625 1626 if (!dssdev->driver) { 1627 dev_warn(&pdev->dev, "no driver for display: %s\n", 1628 dssdev->name); 1629 omap_dss_put_device(dssdev); 1630 continue; 1631 } 1632 1633 vid_dev->displays[vid_dev->num_displays++] = dssdev; 1634 } 1635 1636 if (vid_dev->num_displays == 0) { 1637 dev_err(&pdev->dev, "no displays\n"); 1638 ret = -EINVAL; 1639 goto probe_err0; 1640 } 1641 1642 vid_dev->num_overlays = omap_dss_get_num_overlays(); 1643 for (i = 0; i < vid_dev->num_overlays; i++) 1644 vid_dev->overlays[i] = omap_dss_get_overlay(i); 1645 1646 vid_dev->num_managers = omap_dss_get_num_overlay_managers(); 1647 for (i = 0; i < vid_dev->num_managers; i++) 1648 vid_dev->managers[i] = omap_dss_get_overlay_manager(i); 1649 1650 /* Get the Video1 overlay and video2 overlay. 1651 * Setup the Display attached to that overlays 1652 */ 1653 for (i = 1; i < vid_dev->num_overlays; i++) { 1654 ovl = omap_dss_get_overlay(i); 1655 dssdev = ovl->get_device(ovl); 1656 1657 if (dssdev) { 1658 def_display = dssdev; 1659 } else { 1660 dev_warn(&pdev->dev, "cannot find display\n"); 1661 def_display = NULL; 1662 } 1663 if (def_display) { 1664 struct omap_dss_driver *dssdrv = def_display->driver; 1665 1666 ret = dssdrv->enable(def_display); 1667 if (ret) { 1668 /* Here we are not considering a error 1669 * as display may be enabled by frame 1670 * buffer driver 1671 */ 1672 dev_warn(&pdev->dev, 1673 "'%s' Display already enabled\n", 1674 def_display->name); 1675 } 1676 } 1677 } 1678 1679 if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) { 1680 dev_err(&pdev->dev, "v4l2_device_register failed\n"); 1681 ret = -ENODEV; 1682 goto probe_err1; 1683 } 1684 1685 ret = omap_vout_create_video_devices(pdev); 1686 if (ret) 1687 goto probe_err2; 1688 1689 for (i = 0; i < vid_dev->num_displays; i++) { 1690 struct omap_dss_device *display = vid_dev->displays[i]; 1691 1692 if (display->driver->update) 1693 display->driver->update(display, 0, 0, 1694 display->panel.timings.x_res, 1695 display->panel.timings.y_res); 1696 } 1697 return 0; 1698 1699 probe_err2: 1700 v4l2_device_unregister(&vid_dev->v4l2_dev); 1701 probe_err1: 1702 for (i = 1; i < vid_dev->num_overlays; i++) { 1703 def_display = NULL; 1704 ovl = omap_dss_get_overlay(i); 1705 dssdev = ovl->get_device(ovl); 1706 1707 if (dssdev) 1708 def_display = dssdev; 1709 1710 if (def_display && def_display->driver) 1711 def_display->driver->disable(def_display); 1712 } 1713 probe_err0: 1714 kfree(vid_dev); 1715 err_dss_init: 1716 omapdss_compat_uninit(); 1717 return ret; 1718 } 1719 1720 static struct platform_driver omap_vout_driver = { 1721 .driver = { 1722 .name = VOUT_NAME, 1723 }, 1724 .remove_new = omap_vout_remove, 1725 }; 1726 1727 static int __init omap_vout_init(void) 1728 { 1729 if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { 1730 printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); 1731 return -EINVAL; 1732 } 1733 return 0; 1734 } 1735 1736 static void omap_vout_cleanup(void) 1737 { 1738 platform_driver_unregister(&omap_vout_driver); 1739 } 1740 1741 late_initcall(omap_vout_init); 1742 module_exit(omap_vout_cleanup); 1743