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 54MODULE_AUTHOR("Texas Instruments"); 55MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); 56MODULE_LICENSE("GPL"); 57 58/* Driver Configuration macros */ 59#define VOUT_NAME "omap_vout" 60 61enum omap_vout_channels { 62 OMAP_VIDEO1, 63 OMAP_VIDEO2, 64}; 65 66/* Variables configurable through module params*/ 67static bool vid1_static_vrfb_alloc; 68static bool vid2_static_vrfb_alloc; 69static bool debug; 70 71/* Module parameters */ 72module_param(vid1_static_vrfb_alloc, bool, S_IRUGO); 73MODULE_PARM_DESC(vid1_static_vrfb_alloc, 74 "Static allocation of the VRFB buffer for video1 device"); 75 76module_param(vid2_static_vrfb_alloc, bool, S_IRUGO); 77MODULE_PARM_DESC(vid2_static_vrfb_alloc, 78 "Static allocation of the VRFB buffer for video2 device"); 79 80module_param(debug, bool, S_IRUGO); 81MODULE_PARM_DESC(debug, "Debug level (0-1)"); 82 83/* list of image formats supported by OMAP2 video pipelines */ 84static 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 */ 124static 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 */ 176static 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 200static 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 */ 238static 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 */ 278static int omapvid_setup_overlay(struct omap_vout_device *vout, 279 struct omap_overlay *ovl, int posx, int posy, int outw, 280 int outh, u32 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 347setup_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 */ 355static int omapvid_init(struct omap_vout_device *vout, u32 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 412omapvid_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 */ 420static 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 439static 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; 475err: 476 return 0; 477} 478 479static void omap_vout_isr(void *arg, unsigned int irqstatus) 480{ 481 int ret, fid, mgr_id; 482 u32 addr, irq; 483 struct omap_overlay *ovl; 484 u64 ts; 485 struct omapvideo_info *ovid; 486 struct omap_dss_device *cur_display; 487 struct omap_vout_device *vout = (struct omap_vout_device *)arg; 488 489 ovid = &vout->vid_info; 490 ovl = ovid->overlays[0]; 491 492 mgr_id = ovl->manager->id; 493 494 /* get the display device attached to the overlay */ 495 cur_display = ovl->get_device(ovl); 496 497 if (!cur_display) 498 return; 499 500 spin_lock(&vout->vbq_lock); 501 ts = ktime_get_ns(); 502 503 switch (cur_display->type) { 504 case OMAP_DISPLAY_TYPE_DSI: 505 case OMAP_DISPLAY_TYPE_DPI: 506 case OMAP_DISPLAY_TYPE_DVI: 507 if (mgr_id == OMAP_DSS_CHANNEL_LCD) 508 irq = DISPC_IRQ_VSYNC; 509 else if (mgr_id == OMAP_DSS_CHANNEL_LCD2) 510 irq = DISPC_IRQ_VSYNC2; 511 else 512 goto vout_isr_err; 513 514 if (!(irqstatus & irq)) 515 goto vout_isr_err; 516 break; 517 case OMAP_DISPLAY_TYPE_VENC: 518 fid = omapvid_handle_interlace_display(vout, irqstatus, 519 ts); 520 if (!fid) 521 goto vout_isr_err; 522 break; 523 case OMAP_DISPLAY_TYPE_HDMI: 524 if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) 525 goto vout_isr_err; 526 break; 527 default: 528 goto vout_isr_err; 529 } 530 531 if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { 532 vout->cur_frm->vbuf.vb2_buf.timestamp = ts; 533 vout->cur_frm->vbuf.sequence = vout->sequence++; 534 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE); 535 vout->cur_frm = vout->next_frm; 536 } 537 538 vout->first_int = 0; 539 if (list_empty(&vout->dma_queue)) 540 goto vout_isr_err; 541 542 vout->next_frm = list_entry(vout->dma_queue.next, 543 struct omap_vout_buffer, queue); 544 list_del(&vout->next_frm->queue); 545 546 addr = (unsigned long)vout->queued_buf_addr[vout->next_frm->vbuf.vb2_buf.index] 547 + vout->cropped_offset; 548 549 /* First save the configuration in ovelray structure */ 550 ret = omapvid_init(vout, addr); 551 if (ret) { 552 printk(KERN_ERR VOUT_NAME 553 "failed to set overlay info\n"); 554 goto vout_isr_err; 555 } 556 557 /* Enable the pipeline and set the Go bit */ 558 ret = omapvid_apply_changes(vout); 559 if (ret) 560 printk(KERN_ERR VOUT_NAME "failed to change mode\n"); 561 562vout_isr_err: 563 spin_unlock(&vout->vbq_lock); 564} 565 566 567/* 568 * V4L2 ioctls 569 */ 570static int vidioc_querycap(struct file *file, void *fh, 571 struct v4l2_capability *cap) 572{ 573 struct omap_vout_device *vout = video_drvdata(file); 574 575 strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); 576 strscpy(cap->card, vout->vfd->name, sizeof(cap->card)); 577 snprintf(cap->bus_info, sizeof(cap->bus_info), 578 "platform:%s.%d", VOUT_NAME, vout->vid); 579 return 0; 580} 581 582static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, 583 struct v4l2_fmtdesc *fmt) 584{ 585 int index = fmt->index; 586 587 if (index >= NUM_OUTPUT_FORMATS) 588 return -EINVAL; 589 590 fmt->flags = omap_formats[index].flags; 591 fmt->pixelformat = omap_formats[index].pixelformat; 592 593 return 0; 594} 595 596static int vidioc_g_fmt_vid_out(struct file *file, void *fh, 597 struct v4l2_format *f) 598{ 599 struct omap_vout_device *vout = video_drvdata(file); 600 601 f->fmt.pix = vout->pix; 602 return 0; 603 604} 605 606static int vidioc_try_fmt_vid_out(struct file *file, void *fh, 607 struct v4l2_format *f) 608{ 609 struct omap_overlay *ovl; 610 struct omapvideo_info *ovid; 611 struct omap_video_timings *timing; 612 struct omap_vout_device *vout = video_drvdata(file); 613 struct omap_dss_device *dssdev; 614 615 ovid = &vout->vid_info; 616 ovl = ovid->overlays[0]; 617 /* get the display device attached to the overlay */ 618 dssdev = ovl->get_device(ovl); 619 620 if (!dssdev) 621 return -EINVAL; 622 623 timing = &dssdev->panel.timings; 624 625 vout->fbuf.fmt.height = timing->y_res; 626 vout->fbuf.fmt.width = timing->x_res; 627 628 omap_vout_try_format(&f->fmt.pix); 629 return 0; 630} 631 632static int vidioc_s_fmt_vid_out(struct file *file, void *fh, 633 struct v4l2_format *f) 634{ 635 int ret, bpp; 636 struct omap_overlay *ovl; 637 struct omapvideo_info *ovid; 638 struct omap_video_timings *timing; 639 struct omap_vout_device *vout = video_drvdata(file); 640 struct omap_dss_device *dssdev; 641 642 if (vb2_is_busy(&vout->vq)) 643 return -EBUSY; 644 645 ovid = &vout->vid_info; 646 ovl = ovid->overlays[0]; 647 dssdev = ovl->get_device(ovl); 648 649 /* get the display device attached to the overlay */ 650 if (!dssdev) { 651 ret = -EINVAL; 652 goto s_fmt_vid_out_exit; 653 } 654 timing = &dssdev->panel.timings; 655 656 /* We don't support RGB24-packed mode if vrfb rotation 657 * is enabled*/ 658 if ((is_rotation_enabled(vout)) && 659 f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { 660 ret = -EINVAL; 661 goto s_fmt_vid_out_exit; 662 } 663 664 /* get the framebuffer parameters */ 665 666 if (is_rotation_90_or_270(vout)) { 667 vout->fbuf.fmt.height = timing->x_res; 668 vout->fbuf.fmt.width = timing->y_res; 669 } else { 670 vout->fbuf.fmt.height = timing->y_res; 671 vout->fbuf.fmt.width = timing->x_res; 672 } 673 674 /* change to smaller size is OK */ 675 676 bpp = omap_vout_try_format(&f->fmt.pix); 677 f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp; 678 679 /* try & set the new output format */ 680 vout->bpp = bpp; 681 vout->pix = f->fmt.pix; 682 vout->vrfb_bpp = 1; 683 684 /* If YUYV then vrfb bpp is 2, for others its 1 */ 685 if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || 686 V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) 687 vout->vrfb_bpp = 2; 688 689 /* set default crop and win */ 690 omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win); 691 692 ret = 0; 693 694s_fmt_vid_out_exit: 695 return ret; 696} 697 698static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, 699 struct v4l2_format *f) 700{ 701 int ret = 0; 702 struct omap_vout_device *vout = video_drvdata(file); 703 struct omap_overlay *ovl; 704 struct omapvideo_info *ovid; 705 struct v4l2_window *win = &f->fmt.win; 706 707 ovid = &vout->vid_info; 708 ovl = ovid->overlays[0]; 709 710 ret = omap_vout_try_window(&vout->fbuf, win); 711 712 if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)) 713 win->global_alpha = 0; 714 715 return ret; 716} 717 718static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, 719 struct v4l2_format *f) 720{ 721 int ret = 0; 722 struct omap_overlay *ovl; 723 struct omapvideo_info *ovid; 724 struct omap_vout_device *vout = video_drvdata(file); 725 struct v4l2_window *win = &f->fmt.win; 726 727 ovid = &vout->vid_info; 728 ovl = ovid->overlays[0]; 729 730 ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); 731 if (!ret) { 732 enum omap_dss_trans_key_type key_type = 733 OMAP_DSS_COLOR_KEY_GFX_DST; 734 int enable; 735 736 /* Video1 plane does not support global alpha on OMAP3 */ 737 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) 738 vout->win.global_alpha = win->global_alpha; 739 else 740 win->global_alpha = 0; 741 if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY | 742 V4L2_FBUF_FLAG_SRC_CHROMAKEY)) 743 enable = 1; 744 else 745 enable = 0; 746 if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) 747 key_type = OMAP_DSS_COLOR_KEY_VID_SRC; 748 749 if (ovl->manager && ovl->manager->get_manager_info && 750 ovl->manager->set_manager_info) { 751 struct omap_overlay_manager_info info; 752 753 ovl->manager->get_manager_info(ovl->manager, &info); 754 info.trans_enabled = enable; 755 info.trans_key_type = key_type; 756 info.trans_key = vout->win.chromakey; 757 758 if (ovl->manager->set_manager_info(ovl->manager, &info)) 759 return -EINVAL; 760 } 761 } 762 return ret; 763} 764 765static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, 766 struct v4l2_format *f) 767{ 768 struct omap_overlay *ovl; 769 struct omapvideo_info *ovid; 770 struct omap_vout_device *vout = video_drvdata(file); 771 struct v4l2_window *win = &f->fmt.win; 772 773 ovid = &vout->vid_info; 774 ovl = ovid->overlays[0]; 775 776 win->w = vout->win.w; 777 win->field = vout->win.field; 778 win->chromakey = vout->win.chromakey; 779 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) 780 win->global_alpha = vout->win.global_alpha; 781 else 782 win->global_alpha = 0; 783 win->clips = NULL; 784 win->clipcount = 0; 785 win->bitmap = NULL; 786 return 0; 787} 788 789static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel) 790{ 791 struct omap_vout_device *vout = video_drvdata(file); 792 struct v4l2_pix_format *pix = &vout->pix; 793 794 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 795 return -EINVAL; 796 797 switch (sel->target) { 798 case V4L2_SEL_TGT_CROP: 799 sel->r = vout->crop; 800 break; 801 case V4L2_SEL_TGT_CROP_DEFAULT: 802 omap_vout_default_crop(&vout->pix, &vout->fbuf, &sel->r); 803 break; 804 case V4L2_SEL_TGT_CROP_BOUNDS: 805 /* Width and height are always even */ 806 sel->r.width = pix->width & ~1; 807 sel->r.height = pix->height & ~1; 808 break; 809 default: 810 return -EINVAL; 811 } 812 return 0; 813} 814 815static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel) 816{ 817 int ret = -EINVAL; 818 struct omap_vout_device *vout = video_drvdata(file); 819 struct omapvideo_info *ovid; 820 struct omap_overlay *ovl; 821 struct omap_video_timings *timing; 822 struct omap_dss_device *dssdev; 823 824 if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 825 return -EINVAL; 826 827 if (sel->target != V4L2_SEL_TGT_CROP) 828 return -EINVAL; 829 830 if (vb2_is_busy(&vout->vq)) 831 return -EBUSY; 832 833 ovid = &vout->vid_info; 834 ovl = ovid->overlays[0]; 835 /* get the display device attached to the overlay */ 836 dssdev = ovl->get_device(ovl); 837 838 if (!dssdev) { 839 ret = -EINVAL; 840 goto s_crop_err; 841 } 842 843 timing = &dssdev->panel.timings; 844 845 if (is_rotation_90_or_270(vout)) { 846 vout->fbuf.fmt.height = timing->x_res; 847 vout->fbuf.fmt.width = timing->y_res; 848 } else { 849 vout->fbuf.fmt.height = timing->y_res; 850 vout->fbuf.fmt.width = timing->x_res; 851 } 852 853 ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win, 854 &vout->fbuf, &sel->r); 855 856s_crop_err: 857 return ret; 858} 859 860static int omap_vout_s_ctrl(struct v4l2_ctrl *ctrl) 861{ 862 struct omap_vout_device *vout = 863 container_of(ctrl->handler, struct omap_vout_device, ctrl_handler); 864 int ret = 0; 865 866 switch (ctrl->id) { 867 case V4L2_CID_ROTATE: { 868 struct omapvideo_info *ovid; 869 int rotation = ctrl->val; 870 871 ovid = &vout->vid_info; 872 873 if (rotation && ovid->rotation_type == VOUT_ROT_NONE) { 874 ret = -ERANGE; 875 break; 876 } 877 878 if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 879 ret = -EINVAL; 880 break; 881 } 882 883 if (v4l2_rot_to_dss_rot(rotation, &vout->rotation, 884 vout->mirror)) { 885 ret = -EINVAL; 886 break; 887 } 888 break; 889 } 890 case V4L2_CID_BG_COLOR: 891 { 892 struct omap_overlay *ovl; 893 unsigned int color = ctrl->val; 894 struct omap_overlay_manager_info info; 895 896 ovl = vout->vid_info.overlays[0]; 897 898 if (!ovl->manager || !ovl->manager->get_manager_info) { 899 ret = -EINVAL; 900 break; 901 } 902 903 ovl->manager->get_manager_info(ovl->manager, &info); 904 info.default_color = color; 905 if (ovl->manager->set_manager_info(ovl->manager, &info)) { 906 ret = -EINVAL; 907 break; 908 } 909 break; 910 } 911 case V4L2_CID_VFLIP: 912 { 913 struct omapvideo_info *ovid; 914 unsigned int mirror = ctrl->val; 915 916 ovid = &vout->vid_info; 917 918 if (mirror && ovid->rotation_type == VOUT_ROT_NONE) { 919 ret = -ERANGE; 920 break; 921 } 922 923 if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { 924 ret = -EINVAL; 925 break; 926 } 927 vout->mirror = mirror; 928 break; 929 } 930 default: 931 return -EINVAL; 932 } 933 return ret; 934} 935 936static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = { 937 .s_ctrl = omap_vout_s_ctrl, 938}; 939 940static int omap_vout_vb2_queue_setup(struct vb2_queue *vq, 941 unsigned int *nbufs, 942 unsigned int *num_planes, unsigned int sizes[], 943 struct device *alloc_devs[]) 944{ 945 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 946 int size = vout->pix.sizeimage; 947 948 if (is_rotation_enabled(vout) && vq->num_buffers + *nbufs > VRFB_NUM_BUFS) { 949 *nbufs = VRFB_NUM_BUFS - vq->num_buffers; 950 if (*nbufs == 0) 951 return -EINVAL; 952 } 953 954 if (*num_planes) 955 return sizes[0] < size ? -EINVAL : 0; 956 957 *num_planes = 1; 958 sizes[0] = size; 959 return 0; 960} 961 962static int omap_vout_vb2_prepare(struct vb2_buffer *vb) 963{ 964 struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue); 965 struct omapvideo_info *ovid = &vout->vid_info; 966 struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb); 967 dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); 968 969 if (vb2_plane_size(vb, 0) < vout->pix.sizeimage) { 970 v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, 971 "%s data will not fit into plane (%lu < %u)\n", 972 __func__, vb2_plane_size(vb, 0), vout->pix.sizeimage); 973 return -EINVAL; 974 } 975 976 vb2_set_plane_payload(vb, 0, vout->pix.sizeimage); 977 voutbuf->vbuf.field = V4L2_FIELD_NONE; 978 979 vout->queued_buf_addr[vb->index] = (u8 *)buf_phy_addr; 980 if (ovid->rotation_type == VOUT_ROT_VRFB) 981 return omap_vout_prepare_vrfb(vout, vb); 982 return 0; 983} 984 985static void omap_vout_vb2_queue(struct vb2_buffer *vb) 986{ 987 struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue); 988 struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb); 989 990 list_add_tail(&voutbuf->queue, &vout->dma_queue); 991} 992 993static int omap_vout_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) 994{ 995 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 996 struct omapvideo_info *ovid = &vout->vid_info; 997 struct omap_vout_buffer *buf, *tmp; 998 u32 addr = 0, mask = 0; 999 int ret, j; 1000 1001 /* Get the next frame from the buffer queue */ 1002 vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next, 1003 struct omap_vout_buffer, queue); 1004 /* Remove buffer from the buffer queue */ 1005 list_del(&vout->cur_frm->queue); 1006 /* Initialize field_id and started member */ 1007 vout->field_id = 0; 1008 vout->first_int = 1; 1009 vout->sequence = 0; 1010 1011 if (omap_vout_calculate_offset(vout)) { 1012 ret = -EINVAL; 1013 goto out; 1014 } 1015 if (ovid->rotation_type == VOUT_ROT_VRFB) 1016 if (omap_vout_vrfb_buffer_setup(vout, &count, 0)) { 1017 ret = -ENOMEM; 1018 goto out; 1019 } 1020 1021 addr = (unsigned long)vout->queued_buf_addr[vout->cur_frm->vbuf.vb2_buf.index] 1022 + vout->cropped_offset; 1023 1024 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1025 | DISPC_IRQ_VSYNC2; 1026 1027 /* First save the configuration in overlay structure */ 1028 ret = omapvid_init(vout, addr); 1029 if (ret) { 1030 v4l2_err(&vout->vid_dev->v4l2_dev, 1031 "failed to set overlay info\n"); 1032 goto streamon_err1; 1033 } 1034 1035 omap_dispc_register_isr(omap_vout_isr, vout, mask); 1036 1037 /* Enable the pipeline and set the Go bit */ 1038 ret = omapvid_apply_changes(vout); 1039 if (ret) 1040 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); 1041 1042 for (j = 0; j < ovid->num_overlays; j++) { 1043 struct omap_overlay *ovl = ovid->overlays[j]; 1044 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1045 1046 if (dssdev) { 1047 ret = ovl->enable(ovl); 1048 if (ret) 1049 goto streamon_err1; 1050 } 1051 } 1052 return 0; 1053 1054streamon_err1: 1055 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1056 | DISPC_IRQ_VSYNC2; 1057 1058 omap_dispc_unregister_isr(omap_vout_isr, vout, mask); 1059 1060 for (j = 0; j < ovid->num_overlays; j++) { 1061 struct omap_overlay *ovl = ovid->overlays[j]; 1062 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1063 1064 if (dssdev) 1065 ovl->disable(ovl); 1066 } 1067 /* Turn of the pipeline */ 1068 if (omapvid_apply_changes(vout)) 1069 v4l2_err(&vout->vid_dev->v4l2_dev, 1070 "failed to change mode in streamoff\n"); 1071 1072out: 1073 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); 1074 list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) { 1075 list_del(&buf->queue); 1076 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); 1077 } 1078 return ret; 1079} 1080 1081static void omap_vout_vb2_stop_streaming(struct vb2_queue *vq) 1082{ 1083 struct omap_vout_device *vout = vb2_get_drv_priv(vq); 1084 struct omapvideo_info *ovid = &vout->vid_info; 1085 struct omap_vout_buffer *buf, *tmp; 1086 u32 mask = 0; 1087 int j; 1088 1089 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD 1090 | DISPC_IRQ_VSYNC2; 1091 1092 omap_dispc_unregister_isr(omap_vout_isr, vout, mask); 1093 1094 for (j = 0; j < ovid->num_overlays; j++) { 1095 struct omap_overlay *ovl = ovid->overlays[j]; 1096 struct omap_dss_device *dssdev = ovl->get_device(ovl); 1097 1098 if (dssdev) 1099 ovl->disable(ovl); 1100 } 1101 /* Turn of the pipeline */ 1102 if (omapvid_apply_changes(vout)) 1103 v4l2_err(&vout->vid_dev->v4l2_dev, 1104 "failed to change mode in streamoff\n"); 1105 1106 if (vout->next_frm != vout->cur_frm) 1107 vb2_buffer_done(&vout->next_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1108 vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1109 list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) { 1110 list_del(&buf->queue); 1111 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); 1112 } 1113} 1114 1115static int vidioc_s_fbuf(struct file *file, void *fh, 1116 const struct v4l2_framebuffer *a) 1117{ 1118 int enable = 0; 1119 struct omap_overlay *ovl; 1120 struct omapvideo_info *ovid; 1121 struct omap_vout_device *vout = video_drvdata(file); 1122 struct omap_overlay_manager_info info; 1123 enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 1124 1125 ovid = &vout->vid_info; 1126 ovl = ovid->overlays[0]; 1127 1128 /* OMAP DSS doesn't support Source and Destination color 1129 key together */ 1130 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && 1131 (a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) 1132 return -EINVAL; 1133 /* OMAP DSS Doesn't support the Destination color key 1134 and alpha blending together */ 1135 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) && 1136 (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA)) 1137 return -EINVAL; 1138 1139 if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) { 1140 vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1141 key_type = OMAP_DSS_COLOR_KEY_VID_SRC; 1142 } else 1143 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1144 1145 if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) { 1146 vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; 1147 key_type = OMAP_DSS_COLOR_KEY_GFX_DST; 1148 } else 1149 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; 1150 1151 if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY | 1152 V4L2_FBUF_FLAG_SRC_CHROMAKEY)) 1153 enable = 1; 1154 else 1155 enable = 0; 1156 if (ovl->manager && ovl->manager->get_manager_info && 1157 ovl->manager->set_manager_info) { 1158 1159 ovl->manager->get_manager_info(ovl->manager, &info); 1160 info.trans_enabled = enable; 1161 info.trans_key_type = key_type; 1162 info.trans_key = vout->win.chromakey; 1163 1164 if (ovl->manager->set_manager_info(ovl->manager, &info)) 1165 return -EINVAL; 1166 } 1167 if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) { 1168 vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; 1169 enable = 1; 1170 } else { 1171 vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA; 1172 enable = 0; 1173 } 1174 if (ovl->manager && ovl->manager->get_manager_info && 1175 ovl->manager->set_manager_info) { 1176 ovl->manager->get_manager_info(ovl->manager, &info); 1177 /* enable this only if there is no zorder cap */ 1178 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) 1179 info.partial_alpha_enabled = enable; 1180 if (ovl->manager->set_manager_info(ovl->manager, &info)) 1181 return -EINVAL; 1182 } 1183 1184 return 0; 1185} 1186 1187static int vidioc_g_fbuf(struct file *file, void *fh, 1188 struct v4l2_framebuffer *a) 1189{ 1190 struct omap_overlay *ovl; 1191 struct omapvideo_info *ovid; 1192 struct omap_vout_device *vout = video_drvdata(file); 1193 struct omap_overlay_manager_info info; 1194 struct omap_video_timings *timing; 1195 struct omap_dss_device *dssdev; 1196 1197 ovid = &vout->vid_info; 1198 ovl = ovid->overlays[0]; 1199 /* get the display device attached to the overlay */ 1200 dssdev = ovl->get_device(ovl); 1201 1202 if (!dssdev) 1203 return -EINVAL; 1204 1205 timing = &dssdev->panel.timings; 1206 1207 vout->fbuf.fmt.height = timing->y_res; 1208 vout->fbuf.fmt.width = timing->x_res; 1209 a->fmt.field = V4L2_FIELD_NONE; 1210 a->fmt.colorspace = V4L2_COLORSPACE_SRGB; 1211 a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32; 1212 a->fmt.height = vout->fbuf.fmt.height; 1213 a->fmt.width = vout->fbuf.fmt.width; 1214 a->fmt.bytesperline = vout->fbuf.fmt.width * 4; 1215 a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline; 1216 a->base = vout->fbuf.base; 1217 1218 a->flags = vout->fbuf.flags; 1219 a->capability = vout->fbuf.capability; 1220 a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY | 1221 V4L2_FBUF_FLAG_LOCAL_ALPHA); 1222 1223 if (ovl->manager && ovl->manager->get_manager_info) { 1224 ovl->manager->get_manager_info(ovl->manager, &info); 1225 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC) 1226 a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; 1227 if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST) 1228 a->flags |= V4L2_FBUF_FLAG_CHROMAKEY; 1229 if (info.partial_alpha_enabled) 1230 a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; 1231 } 1232 1233 return 0; 1234} 1235 1236static int vidioc_enum_output(struct file *file, void *priv_fh, 1237 struct v4l2_output *out) 1238{ 1239 if (out->index) 1240 return -EINVAL; 1241 snprintf(out->name, sizeof(out->name), "Overlay"); 1242 out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; 1243 return 0; 1244} 1245 1246static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i) 1247{ 1248 *i = 0; 1249 return 0; 1250} 1251 1252static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i) 1253{ 1254 return i ? -EINVAL : 0; 1255} 1256 1257static const struct v4l2_ioctl_ops vout_ioctl_ops = { 1258 .vidioc_querycap = vidioc_querycap, 1259 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, 1260 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, 1261 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, 1262 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, 1263 .vidioc_s_fbuf = vidioc_s_fbuf, 1264 .vidioc_g_fbuf = vidioc_g_fbuf, 1265 .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_overlay, 1266 .vidioc_s_fmt_vid_out_overlay = vidioc_s_fmt_vid_overlay, 1267 .vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_overlay, 1268 .vidioc_g_selection = vidioc_g_selection, 1269 .vidioc_s_selection = vidioc_s_selection, 1270 .vidioc_enum_output = vidioc_enum_output, 1271 .vidioc_g_output = vidioc_g_output, 1272 .vidioc_s_output = vidioc_s_output, 1273 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1274 .vidioc_create_bufs = vb2_ioctl_create_bufs, 1275 .vidioc_querybuf = vb2_ioctl_querybuf, 1276 .vidioc_qbuf = vb2_ioctl_qbuf, 1277 .vidioc_dqbuf = vb2_ioctl_dqbuf, 1278 .vidioc_expbuf = vb2_ioctl_expbuf, 1279 .vidioc_streamon = vb2_ioctl_streamon, 1280 .vidioc_streamoff = vb2_ioctl_streamoff, 1281 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1282 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1283}; 1284 1285static const struct v4l2_file_operations omap_vout_fops = { 1286 .owner = THIS_MODULE, 1287 .unlocked_ioctl = video_ioctl2, 1288 .poll = vb2_fop_poll, 1289 .mmap = vb2_fop_mmap, 1290 .open = v4l2_fh_open, 1291 .release = vb2_fop_release, 1292}; 1293 1294static const struct vb2_ops omap_vout_vb2_ops = { 1295 .queue_setup = omap_vout_vb2_queue_setup, 1296 .buf_queue = omap_vout_vb2_queue, 1297 .buf_prepare = omap_vout_vb2_prepare, 1298 .start_streaming = omap_vout_vb2_start_streaming, 1299 .stop_streaming = omap_vout_vb2_stop_streaming, 1300 .wait_prepare = vb2_ops_wait_prepare, 1301 .wait_finish = vb2_ops_wait_finish, 1302}; 1303 1304/* Init functions used during driver initialization */ 1305/* Initial setup of video_data */ 1306static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) 1307{ 1308 struct video_device *vfd; 1309 struct v4l2_pix_format *pix; 1310 struct omap_overlay *ovl = vout->vid_info.overlays[0]; 1311 struct omap_dss_device *display = ovl->get_device(ovl); 1312 struct v4l2_ctrl_handler *hdl; 1313 struct vb2_queue *vq; 1314 int ret; 1315 1316 /* set the default pix */ 1317 pix = &vout->pix; 1318 1319 /* Set the default picture of QVGA */ 1320 pix->width = QQVGA_WIDTH; 1321 pix->height = QQVGA_HEIGHT; 1322 1323 /* Default pixel format is RGB 5-6-5 */ 1324 pix->pixelformat = V4L2_PIX_FMT_RGB565; 1325 pix->field = V4L2_FIELD_NONE; 1326 pix->bytesperline = pix->width * 2; 1327 pix->sizeimage = pix->bytesperline * pix->height; 1328 pix->colorspace = V4L2_COLORSPACE_SRGB; 1329 1330 vout->bpp = RGB565_BPP; 1331 vout->fbuf.fmt.width = display->panel.timings.x_res; 1332 vout->fbuf.fmt.height = display->panel.timings.y_res; 1333 vout->cropped_offset = 0; 1334 1335 /* Set the data structures for the overlay parameters*/ 1336 vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY; 1337 vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA | 1338 V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY | 1339 V4L2_FBUF_CAP_EXTERNOVERLAY; 1340 if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) { 1341 vout->win.global_alpha = 255; 1342 vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA; 1343 vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; 1344 } else { 1345 vout->win.global_alpha = 0; 1346 } 1347 vout->win.field = V4L2_FIELD_NONE; 1348 1349 omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win); 1350 1351 hdl = &vout->ctrl_handler; 1352 v4l2_ctrl_handler_init(hdl, 3); 1353 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) { 1354 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1355 V4L2_CID_ROTATE, 0, 270, 90, 0); 1356 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1357 V4L2_CID_VFLIP, 0, 1, 1, 0); 1358 } 1359 v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops, 1360 V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0); 1361 if (hdl->error) 1362 return hdl->error; 1363 1364 vout->rotation = 0; 1365 vout->mirror = false; 1366 INIT_LIST_HEAD(&vout->dma_queue); 1367 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) 1368 vout->vrfb_bpp = 2; 1369 1370 /* initialize the video_device struct */ 1371 vfd = vout->vfd = video_device_alloc(); 1372 1373 if (!vfd) { 1374 printk(KERN_ERR VOUT_NAME 1375 ": could not allocate video device struct\n"); 1376 v4l2_ctrl_handler_free(hdl); 1377 return -ENOMEM; 1378 } 1379 vfd->ctrl_handler = hdl; 1380 vfd->release = video_device_release; 1381 vfd->ioctl_ops = &vout_ioctl_ops; 1382 1383 strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); 1384 1385 vfd->fops = &omap_vout_fops; 1386 vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; 1387 vfd->vfl_dir = VFL_DIR_TX; 1388 vfd->minor = -1; 1389 vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | 1390 V4L2_CAP_VIDEO_OUTPUT_OVERLAY; 1391 mutex_init(&vout->lock); 1392 1393 vq = &vout->vq; 1394 vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 1395 vq->io_modes = VB2_MMAP | VB2_DMABUF; 1396 vq->drv_priv = vout; 1397 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1398 vq->buf_struct_size = sizeof(struct omap_vout_buffer); 1399 vq->dev = vfd->v4l2_dev->dev; 1400 1401 vq->ops = &omap_vout_vb2_ops; 1402 vq->mem_ops = &vb2_dma_contig_memops; 1403 vq->lock = &vout->lock; 1404 vq->min_buffers_needed = 1; 1405 vfd->queue = vq; 1406 1407 ret = vb2_queue_init(vq); 1408 if (ret) { 1409 v4l2_ctrl_handler_free(hdl); 1410 video_device_release(vfd); 1411 } 1412 return ret; 1413} 1414 1415/* Setup video buffers */ 1416static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, 1417 int vid_num) 1418{ 1419 struct omapvideo_info *ovid; 1420 struct omap_vout_device *vout; 1421 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1422 struct omap2video_device *vid_dev = 1423 container_of(v4l2_dev, struct omap2video_device, v4l2_dev); 1424 int ret = 0; 1425 1426 vout = vid_dev->vouts[vid_num]; 1427 ovid = &vout->vid_info; 1428 1429 if (ovid->rotation_type == VOUT_ROT_VRFB) { 1430 bool static_vrfb_allocation = (vid_num == 0) ? 1431 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; 1432 ret = omap_vout_setup_vrfb_bufs(pdev, vid_num, 1433 static_vrfb_allocation); 1434 } 1435 return ret; 1436} 1437 1438/* Create video out devices */ 1439static int __init omap_vout_create_video_devices(struct platform_device *pdev) 1440{ 1441 int ret = 0, k; 1442 struct omap_vout_device *vout; 1443 struct video_device *vfd = NULL; 1444 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1445 struct omap2video_device *vid_dev = container_of(v4l2_dev, 1446 struct omap2video_device, v4l2_dev); 1447 struct omap_overlay *ovl = vid_dev->overlays[0]; 1448 struct omap_overlay_info info; 1449 1450 ovl->get_overlay_info(ovl, &info); 1451 1452 for (k = 0; k < pdev->num_resources; k++) { 1453 1454 vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL); 1455 if (!vout) { 1456 dev_err(&pdev->dev, ": could not allocate memory\n"); 1457 return -ENOMEM; 1458 } 1459 1460 vout->vid = k; 1461 vid_dev->vouts[k] = vout; 1462 vout->vid_dev = vid_dev; 1463 /* Select video2 if only 1 overlay is controlled by V4L2 */ 1464 if (pdev->num_resources == 1) 1465 vout->vid_info.overlays[0] = vid_dev->overlays[k + 2]; 1466 else 1467 /* Else select video1 and video2 one by one. */ 1468 vout->vid_info.overlays[0] = vid_dev->overlays[k + 1]; 1469 vout->vid_info.num_overlays = 1; 1470 vout->vid_info.id = k + 1; 1471 spin_lock_init(&vout->vbq_lock); 1472 /* 1473 * Set the framebuffer base, this allows applications to find 1474 * the fb corresponding to this overlay. 1475 * 1476 * To be precise: fbuf.base should match smem_start of 1477 * struct fb_fix_screeninfo. 1478 */ 1479 vout->fbuf.base = (void *)info.paddr; 1480 1481 /* Set VRFB as rotation_type for omap2 and omap3 */ 1482 if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx()) 1483 vout->vid_info.rotation_type = VOUT_ROT_VRFB; 1484 1485 /* Setup the default configuration for the video devices 1486 */ 1487 if (omap_vout_setup_video_data(vout) != 0) { 1488 ret = -ENOMEM; 1489 goto error; 1490 } 1491 1492 /* Allocate default number of buffers for the video streaming 1493 * and reserve the VRFB space for rotation 1494 */ 1495 if (omap_vout_setup_video_bufs(pdev, k) != 0) { 1496 ret = -ENOMEM; 1497 goto error1; 1498 } 1499 1500 /* Register the Video device with V4L2 1501 */ 1502 vfd = vout->vfd; 1503 if (video_register_device(vfd, VFL_TYPE_VIDEO, -1) < 0) { 1504 dev_err(&pdev->dev, 1505 ": Could not register Video for Linux device\n"); 1506 vfd->minor = -1; 1507 ret = -ENODEV; 1508 goto error2; 1509 } 1510 video_set_drvdata(vfd, vout); 1511 1512 dev_info(&pdev->dev, 1513 ": registered and initialized video device %d\n", 1514 vfd->minor); 1515 if (k == (pdev->num_resources - 1)) 1516 return 0; 1517 1518 continue; 1519error2: 1520 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) 1521 omap_vout_release_vrfb(vout); 1522error1: 1523 video_device_release(vfd); 1524error: 1525 kfree(vout); 1526 return ret; 1527 } 1528 1529 return -ENODEV; 1530} 1531/* Driver functions */ 1532static void omap_vout_cleanup_device(struct omap_vout_device *vout) 1533{ 1534 struct video_device *vfd; 1535 struct omapvideo_info *ovid; 1536 1537 if (!vout) 1538 return; 1539 1540 vfd = vout->vfd; 1541 ovid = &vout->vid_info; 1542 if (vfd) { 1543 if (!video_is_registered(vfd)) { 1544 /* 1545 * The device was never registered, so release the 1546 * video_device struct directly. 1547 */ 1548 video_device_release(vfd); 1549 } else { 1550 /* 1551 * The unregister function will release the video_device 1552 * struct as well as unregistering it. 1553 */ 1554 video_unregister_device(vfd); 1555 } 1556 } 1557 v4l2_ctrl_handler_free(&vout->ctrl_handler); 1558 if (ovid->rotation_type == VOUT_ROT_VRFB) { 1559 omap_vout_release_vrfb(vout); 1560 /* Free the VRFB buffer if allocated 1561 * init time 1562 */ 1563 if (vout->vrfb_static_allocation) 1564 omap_vout_free_vrfb_buffers(vout); 1565 } 1566 1567 kfree(vout); 1568} 1569 1570static int omap_vout_remove(struct platform_device *pdev) 1571{ 1572 int k; 1573 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); 1574 struct omap2video_device *vid_dev = container_of(v4l2_dev, struct 1575 omap2video_device, v4l2_dev); 1576 1577 v4l2_device_unregister(v4l2_dev); 1578 for (k = 0; k < pdev->num_resources; k++) 1579 omap_vout_cleanup_device(vid_dev->vouts[k]); 1580 1581 for (k = 0; k < vid_dev->num_displays; k++) { 1582 if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) 1583 vid_dev->displays[k]->driver->disable(vid_dev->displays[k]); 1584 1585 omap_dss_put_device(vid_dev->displays[k]); 1586 } 1587 kfree(vid_dev); 1588 return 0; 1589} 1590 1591static int __init omap_vout_probe(struct platform_device *pdev) 1592{ 1593 int ret = 0, i; 1594 struct omap_overlay *ovl; 1595 struct omap_dss_device *dssdev = NULL; 1596 struct omap_dss_device *def_display; 1597 struct omap2video_device *vid_dev = NULL; 1598 1599 if (omapdss_is_initialized() == false) 1600 return -EPROBE_DEFER; 1601 1602 ret = omapdss_compat_init(); 1603 if (ret) { 1604 dev_err(&pdev->dev, "failed to init dss\n"); 1605 return ret; 1606 } 1607 1608 if (pdev->num_resources == 0) { 1609 dev_err(&pdev->dev, "probed for an unknown device\n"); 1610 ret = -ENODEV; 1611 goto err_dss_init; 1612 } 1613 1614 vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); 1615 if (vid_dev == NULL) { 1616 ret = -ENOMEM; 1617 goto err_dss_init; 1618 } 1619 1620 vid_dev->num_displays = 0; 1621 for_each_dss_dev(dssdev) { 1622 omap_dss_get_device(dssdev); 1623 1624 if (!dssdev->driver) { 1625 dev_warn(&pdev->dev, "no driver for display: %s\n", 1626 dssdev->name); 1627 omap_dss_put_device(dssdev); 1628 continue; 1629 } 1630 1631 vid_dev->displays[vid_dev->num_displays++] = dssdev; 1632 } 1633 1634 if (vid_dev->num_displays == 0) { 1635 dev_err(&pdev->dev, "no displays\n"); 1636 ret = -EINVAL; 1637 goto probe_err0; 1638 } 1639 1640 vid_dev->num_overlays = omap_dss_get_num_overlays(); 1641 for (i = 0; i < vid_dev->num_overlays; i++) 1642 vid_dev->overlays[i] = omap_dss_get_overlay(i); 1643 1644 vid_dev->num_managers = omap_dss_get_num_overlay_managers(); 1645 for (i = 0; i < vid_dev->num_managers; i++) 1646 vid_dev->managers[i] = omap_dss_get_overlay_manager(i); 1647 1648 /* Get the Video1 overlay and video2 overlay. 1649 * Setup the Display attached to that overlays 1650 */ 1651 for (i = 1; i < vid_dev->num_overlays; i++) { 1652 ovl = omap_dss_get_overlay(i); 1653 dssdev = ovl->get_device(ovl); 1654 1655 if (dssdev) { 1656 def_display = dssdev; 1657 } else { 1658 dev_warn(&pdev->dev, "cannot find display\n"); 1659 def_display = NULL; 1660 } 1661 if (def_display) { 1662 struct omap_dss_driver *dssdrv = def_display->driver; 1663 1664 ret = dssdrv->enable(def_display); 1665 if (ret) { 1666 /* Here we are not considering a error 1667 * as display may be enabled by frame 1668 * buffer driver 1669 */ 1670 dev_warn(&pdev->dev, 1671 "'%s' Display already enabled\n", 1672 def_display->name); 1673 } 1674 } 1675 } 1676 1677 if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) { 1678 dev_err(&pdev->dev, "v4l2_device_register failed\n"); 1679 ret = -ENODEV; 1680 goto probe_err1; 1681 } 1682 1683 ret = omap_vout_create_video_devices(pdev); 1684 if (ret) 1685 goto probe_err2; 1686 1687 for (i = 0; i < vid_dev->num_displays; i++) { 1688 struct omap_dss_device *display = vid_dev->displays[i]; 1689 1690 if (display->driver->update) 1691 display->driver->update(display, 0, 0, 1692 display->panel.timings.x_res, 1693 display->panel.timings.y_res); 1694 } 1695 return 0; 1696 1697probe_err2: 1698 v4l2_device_unregister(&vid_dev->v4l2_dev); 1699probe_err1: 1700 for (i = 1; i < vid_dev->num_overlays; i++) { 1701 def_display = NULL; 1702 ovl = omap_dss_get_overlay(i); 1703 dssdev = ovl->get_device(ovl); 1704 1705 if (dssdev) 1706 def_display = dssdev; 1707 1708 if (def_display && def_display->driver) 1709 def_display->driver->disable(def_display); 1710 } 1711probe_err0: 1712 kfree(vid_dev); 1713err_dss_init: 1714 omapdss_compat_uninit(); 1715 return ret; 1716} 1717 1718static struct platform_driver omap_vout_driver = { 1719 .driver = { 1720 .name = VOUT_NAME, 1721 }, 1722 .remove = omap_vout_remove, 1723}; 1724 1725static int __init omap_vout_init(void) 1726{ 1727 if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { 1728 printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); 1729 return -EINVAL; 1730 } 1731 return 0; 1732} 1733 1734static void omap_vout_cleanup(void) 1735{ 1736 platform_driver_unregister(&omap_vout_driver); 1737} 1738 1739late_initcall(omap_vout_init); 1740module_exit(omap_vout_cleanup); 1741