staging: bcm2835-camera: Fix duplicate definition of module information
[platform/kernel/linux-rpi.git] / drivers / staging / vc04_services / bcm2835-camera / bcm2835-camera.c
index 7a587f4..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,18 +364,15 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
                return;
        }
 
-       if (length == 0) {
+       if (mmal_buf->length == 0) {
                /* stream ended */
-               if (buf) {
-                       /* this should only ever happen if the port is
-                        * disabled and there are buffers still queued
+               if (dev->capture.frame_count) {
+                       /* empty buffer whilst capturing - expected to be an
+                        * EOS, so grab another frame
                         */
-                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-                       pr_debug("Empty buffer");
-               } else if (dev->capture.frame_count) {
-                       /* grab another frame */
                        if (is_capturing(dev)) {
-                               pr_debug("Grab another frame");
+                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                                        "Grab another frame");
                                vchiq_mmal_port_parameter_set(
                                        instance,
                                        dev->capture.camera_port,
@@ -356,8 +380,15 @@ 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->mmal))
+                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                                        "Failed to return EOS buffer");
                } else {
-                       /* signal frame completion */
+                       /* stopping streaming.
+                        * return buffer, and signal frame completion
+                        */
+                       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
                        complete(&dev->capture.frame_cmplt);
                }
                return;
@@ -379,17 +410,22 @@ 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,
+                                "Negative delta - using last time\n");
+                       timestamp = dev->capture.last_timestamp;
+               }
                buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp);
        } else {
                if (dev->capture.last_timestamp) {
@@ -406,17 +442,18 @@ 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);
+                "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");
@@ -499,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__);
@@ -535,6 +574,9 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
        /* enable frame capture */
        dev->capture.frame_count = 1;
 
+       /* reset sequence number */
+       dev->capture.sequence = 0;
+
        /* if the preview is not already running, wait for a few frames for AGC
         * to settle down.
         */
@@ -581,8 +623,8 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
            vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
        if (ret) {
                v4l2_err(&dev->v4l2_dev,
-                       "Failed to enable capture port - error %d. Disabling camera port again\n",
-                       ret);
+                        "Failed to enable capture port - error %d. Disabling camera port again\n",
+                        ret);
 
                vchiq_mmal_port_disable(dev->instance,
                                        dev->capture.camera_port);
@@ -608,6 +650,7 @@ static void stop_streaming(struct vb2_queue *vq)
        int ret;
        unsigned long timeout;
        struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
+       struct vchiq_mmal_port *port = dev->capture.port;
 
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
                 __func__, dev);
@@ -616,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;
@@ -631,26 +674,35 @@ static void stop_streaming(struct vb2_queue *vq)
                                      &dev->capture.frame_count,
                                      sizeof(dev->capture.frame_count));
 
-       /* wait for last frame to complete */
-       timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
-       if (timeout == 0)
-               v4l2_err(&dev->v4l2_dev,
-                        "timed out waiting for frame completion\n");
-
        v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
                 "disabling connection\n");
 
        /* 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);
        }
 
+       /* wait for all buffers to be returned */
+       while (atomic_read(&port->buffers_with_vpu)) {
+               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+                        "%s: Waiting for buffers to be returned - %d outstanding\n",
+                        __func__, atomic_read(&port->buffers_with_vpu));
+               timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt,
+                                                     HZ);
+               if (timeout == 0) {
+                       v4l2_err(&dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
+                                __func__,
+                                atomic_read(&port->buffers_with_vpu));
+                       break;
+               }
+       }
+
        if (disable_camera(dev) < 0)
                v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n");
 }
@@ -973,14 +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
@@ -1045,11 +1110,12 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
                /* Make a further decision on port based on resolution */
                if (f->fmt.pix.width <= max_video_width &&
                    f->fmt.pix.height <= max_video_height)
-                       camera_port = port =
+                       camera_port =
                            &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
                else
-                       camera_port = port =
+                       camera_port =
                            &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+               port = camera_port;
                break;
        case COMP_IMAGE_ENCODE:
                encode_component = dev->component[COMP_IMAGE_ENCODE];
@@ -1325,7 +1391,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 }
 
 static int vidioc_enum_framesizes(struct file *file, void *fh,
-                          struct v4l2_frmsizeenum *fsize)
+                                 struct v4l2_frmsizeenum *fsize)
 {
        struct bm2835_mmal_dev *dev = video_drvdata(file);
        static const struct v4l2_frmsize_stepwise sizes = {
@@ -1914,7 +1980,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev)
                ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
                if (ret < 0) {
                        v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n",
-                               __func__, ret);
+                                __func__, ret);
                        goto unreg_dev;
                }
                dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
@@ -1924,7 +1990,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev)
                ret = mmal_init(dev);
                if (ret < 0) {
                        v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n",
-                               __func__, ret);
+                                __func__, ret);
                        goto unreg_dev;
                }
                /* initialize queue */
@@ -1933,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;
@@ -1946,7 +2012,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev)
                ret = bm2835_mmal_init_device(dev, &dev->vdev);
                if (ret < 0) {
                        v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n",
-                               __func__, ret);
+                                __func__, ret);
                        goto unreg_dev;
                }
 
@@ -1956,7 +2022,7 @@ static int bcm2835_mmal_probe(struct platform_device *pdev)
                ret = mmal_setup_components(dev, &default_v4l2_format);
                if (ret < 0) {
                        v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n",
-                               __func__, ret);
+                                __func__, ret);
                        goto unreg_dev;
                }