root/drivers/media/platform/omap/omap_vout.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. omap_vout_try_format
  2. v4l2_rot_to_dss_rot
  3. omap_vout_calculate_offset
  4. video_mode_to_dss_mode
  5. omapvid_setup_overlay
  6. omapvid_init
  7. omapvid_apply_changes
  8. omapvid_handle_interlace_display
  9. omap_vout_isr
  10. vidioc_querycap
  11. vidioc_enum_fmt_vid_out
  12. vidioc_g_fmt_vid_out
  13. vidioc_try_fmt_vid_out
  14. vidioc_s_fmt_vid_out
  15. vidioc_try_fmt_vid_overlay
  16. vidioc_s_fmt_vid_overlay
  17. vidioc_g_fmt_vid_overlay
  18. vidioc_g_selection
  19. vidioc_s_selection
  20. omap_vout_s_ctrl
  21. omap_vout_vb2_queue_setup
  22. omap_vout_vb2_prepare
  23. omap_vout_vb2_queue
  24. omap_vout_vb2_start_streaming
  25. omap_vout_vb2_stop_streaming
  26. vidioc_s_fbuf
  27. vidioc_g_fbuf
  28. vidioc_enum_output
  29. vidioc_g_output
  30. vidioc_s_output
  31. omap_vout_setup_video_data
  32. omap_vout_setup_video_bufs
  33. omap_vout_create_video_devices
  34. omap_vout_cleanup_device
  35. omap_vout_remove
  36. omap_vout_probe
  37. omap_vout_init
  38. omap_vout_cleanup

   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, 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 
 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, 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 
 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         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 
 562 vout_isr_err:
 563         spin_unlock(&vout->vbq_lock);
 564 }
 565 
 566 
 567 /*
 568  * V4L2 ioctls
 569  */
 570 static 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 
 582 static 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 
 596 static 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 
 606 static 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 
 632 static 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 
 694 s_fmt_vid_out_exit:
 695         return ret;
 696 }
 697 
 698 static 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 
 718 static 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 
 765 static 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 
 789 static 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 
 815 static 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 
 856 s_crop_err:
 857         return ret;
 858 }
 859 
 860 static 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 
 936 static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = {
 937         .s_ctrl = omap_vout_s_ctrl,
 938 };
 939 
 940 static 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 
 962 static 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 
 985 static 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 
 993 static 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 
1054 streamon_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 
1072 out:
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 
1081 static 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 
1115 static 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 
1187 static 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 
1236 static 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 
1246 static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i)
1247 {
1248         *i = 0;
1249         return 0;
1250 }
1251 
1252 static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i)
1253 {
1254         return i ? -EINVAL : 0;
1255 }
1256 
1257 static 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 
1285 static 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 
1294 static 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 */
1306 static 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 */
1416 static 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 */
1439 static 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_GRABBER, -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;
1519 error2:
1520                 if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
1521                         omap_vout_release_vrfb(vout);
1522 error1:
1523                 video_device_release(vfd);
1524 error:
1525                 kfree(vout);
1526                 return ret;
1527         }
1528 
1529         return -ENODEV;
1530 }
1531 /* Driver functions */
1532 static 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 
1570 static 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 
1591 static 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 
1697 probe_err2:
1698         v4l2_device_unregister(&vid_dev->v4l2_dev);
1699 probe_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         }
1711 probe_err0:
1712         kfree(vid_dev);
1713 err_dss_init:
1714         omapdss_compat_uninit();
1715         return ret;
1716 }
1717 
1718 static struct platform_driver omap_vout_driver = {
1719         .driver = {
1720                 .name = VOUT_NAME,
1721         },
1722         .remove = omap_vout_remove,
1723 };
1724 
1725 static 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 
1734 static void omap_vout_cleanup(void)
1735 {
1736         platform_driver_unregister(&omap_vout_driver);
1737 }
1738 
1739 late_initcall(omap_vout_init);
1740 module_exit(omap_vout_cleanup);

/* [<][>][^][v][top][bottom][index][help] */