staging: bcm2835-camera: Fix duplicate definition of module information
[platform/kernel/linux-rpi.git] / drivers / staging / vc04_services / bcm2835-camera / bcm2835-camera.c
index e057d84..a8f3ce5 100644 (file)
@@ -72,6 +72,12 @@ static const struct v4l2_fract
        tpf_max     = {.numerator = 1,          .denominator = FPS_MIN},
        tpf_default = {.numerator = 1000,       .denominator = 30000};
 
+/* Container for MMAL and VB2 buffers*/
+struct vb2_mmal_buffer {
+       struct vb2_v4l2_buffer  vb;
+       struct mmal_buffer      mmal;
+};
+
 /* video formats */
 static struct mmal_fmt formats[] = {
        {
@@ -236,6 +242,22 @@ static int queue_setup(struct vb2_queue *vq,
                return -EINVAL;
        }
 
+       /* Handle CREATE_BUFS situation - *nplanes != 0 */
+       if (*nplanes) {
+               if (*nplanes != 1 ||
+                   sizes[0] < dev->capture.port->current_buffer.size) {
+                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                                "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
+                                __func__, dev, sizes[0],
+                                dev->capture.port->current_buffer.size,
+                                *nplanes);
+                       return -EINVAL;
+               } else {
+                       return 0;
+               }
+       }
+
+       /* Handle REQBUFS situation */
        size = dev->capture.port->current_buffer.size;
        if (size == 0) {
                v4l2_err(&dev->v4l2_dev,
@@ -267,14 +289,15 @@ static int buffer_init(struct vb2_buffer *vb)
 {
        struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
        struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-       struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+       struct vb2_mmal_buffer *buf =
+                               container_of(vb2, struct vb2_mmal_buffer, vb);
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
                 __func__, dev, vb);
-       buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-       buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+       buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+       buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
 
-       return mmal_vchi_buffer_init(dev->instance, buf);
+       return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
 }
 
 static int buffer_prepare(struct vb2_buffer *vb)
@@ -303,11 +326,13 @@ static void buffer_cleanup(struct vb2_buffer *vb)
 {
        struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
        struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-       struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+       struct vb2_mmal_buffer *buf =
+                               container_of(vb2, struct vb2_mmal_buffer, vb);
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
                 __func__, dev, vb);
-       mmal_vchi_buffer_cleanup(buf);
+
+       mmal_vchi_buffer_cleanup(&buf->mmal);
 }
 
 static inline bool is_capturing(struct bm2835_mmal_dev *dev)
@@ -319,14 +344,16 @@ static inline bool is_capturing(struct bm2835_mmal_dev *dev)
 static void buffer_cb(struct vchiq_mmal_instance *instance,
                      struct vchiq_mmal_port *port,
                      int status,
-                     struct mmal_buffer *buf,
-                     unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
+                     struct mmal_buffer *mmal_buf)
 {
        struct bm2835_mmal_dev *dev = port->cb_ctx;
+       struct vb2_mmal_buffer *buf =
+                       container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                 "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
-                __func__, status, buf, length, mmal_flags, pts);
+                __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
+                mmal_buf->pts);
 
        if (status != 0) {
                /* error in transfer */
@@ -337,7 +364,7 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                return;
        }
 
-       if (length == 0) {
+       if (mmal_buf->length == 0) {
                /* stream ended */
                if (dev->capture.frame_count) {
                        /* empty buffer whilst capturing - expected to be an
@@ -353,7 +380,8 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                                        &dev->capture.frame_count,
                                        sizeof(dev->capture.frame_count));
                        }
-                       if (vchiq_mmal_submit_buffer(instance, port, buf))
+                       if (vchiq_mmal_submit_buffer(instance, port,
+                                                    &buf->mmal))
                                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                                         "Failed to return EOS buffer");
                } else {
@@ -382,16 +410,16 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                         "Buffer time set as current time - %lld",
                         buf->vb.vb2_buf.timestamp);
-       } else if (pts != 0) {
+       } else if (mmal_buf->pts != 0) {
                ktime_t timestamp;
-               s64 runtime_us = pts -
+               s64 runtime_us = mmal_buf->pts -
                    dev->capture.vc_start_timestamp;
                timestamp = ktime_add_us(dev->capture.kernel_start_ts,
                                         runtime_us);
                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                         "Convert start time %llu and %llu with offset %llu to %llu\n",
                         ktime_to_ns(dev->capture.kernel_start_ts),
-                        dev->capture.vc_start_timestamp, pts,
+                        dev->capture.vc_start_timestamp, mmal_buf->pts,
                         ktime_to_ns(timestamp));
                if (timestamp < dev->capture.last_timestamp) {
                        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
@@ -415,16 +443,17 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
        }
        dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
        buf->vb.sequence = dev->capture.sequence++;
+       buf->vb.field = V4L2_FIELD_NONE;
 
-       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
-       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
+       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
                buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                 "Buffer has ts %llu", dev->capture.last_timestamp);
        vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
-       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+       if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
            is_capturing(dev)) {
                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                         "Grab another frame as buffer has EOS");
@@ -507,14 +536,16 @@ static void buffer_queue(struct vb2_buffer *vb)
 {
        struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
        struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
-       struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+       struct vb2_mmal_buffer *buf =
+                               container_of(vb2, struct vb2_mmal_buffer, vb);
        int ret;
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                 "%s: dev:%p buf:%p, idx %u\n",
                 __func__, dev, buf, vb2->vb2_buf.index);
 
-       ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
+       ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
+                                      &buf->mmal);
        if (ret < 0)
                v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
                         __func__);
@@ -628,7 +659,7 @@ static void stop_streaming(struct vb2_queue *vq)
        dev->capture.frame_count = 0;
 
        /* ensure a format has actually been set */
-       if (!dev->capture.port) {
+       if (!port) {
                v4l2_err(&dev->v4l2_dev,
                         "no capture port - stream not started?\n");
                return;
@@ -648,11 +679,11 @@ static void stop_streaming(struct vb2_queue *vq)
 
        /* disable the connection from camera to encoder */
        ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
-       if (!ret && dev->capture.camera_port != dev->capture.port) {
+       if (!ret && dev->capture.camera_port != port) {
                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                         "disabling port\n");
-               ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
-       } else if (dev->capture.camera_port != dev->capture.port) {
+               ret = vchiq_mmal_port_disable(dev->instance, port);
+       } else if (dev->capture.camera_port != port) {
                v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
                         ret);
        }
@@ -994,13 +1025,27 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                              1, 0);
        f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
        if (!mfmt->remove_padding) {
-               int align_mask = ((32 * mfmt->depth) >> 3) - 1;
-               /* GPU isn't removing padding, so stride is aligned to 32 */
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
+               if (mfmt->depth == 24) {
+                       /*
+                        * 24bpp is a pain as we can't use simple masking.
+                        * Min stride is width aligned to 16, times 24bpp.
+                        */
+                       f->fmt.pix.bytesperline =
+                               ((f->fmt.pix.width + 15) & ~15) * 3;
+               } else {
+                       /*
+                        * GPU isn't removing padding, so stride is aligned to
+                        * 32
+                        */
+                       int align_mask = ((32 * mfmt->depth) >> 3) - 1;
+
+                       f->fmt.pix.bytesperline =
+                               (f->fmt.pix.bytesperline + align_mask) &
+                                                       ~align_mask;
+               }
                v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-                        "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
-                        f->fmt.pix.bytesperline, align_mask);
+                        "Not removing padding, so bytes/line = %d\n",
+                        f->fmt.pix.bytesperline);
        }
 
        /* Image buffer has to be padded to allow for alignment, even though
@@ -1954,7 +1999,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev)
                q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
                q->drv_priv = dev;
-               q->buf_struct_size = sizeof(struct mmal_buffer);
+               q->buf_struct_size = sizeof(struct vb2_mmal_buffer);
                q->ops = &bm2835_mmal_video_qops;
                q->mem_ops = &vb2_vmalloc_memops;
                q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;