These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / input / touchscreen / sur40.c
index a24eba5..d214f22 100644 (file)
@@ -38,6 +38,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-sg.h>
 
 /* read 512 bytes from endpoint 0x86 -> get header + blobs */
@@ -125,7 +126,7 @@ struct sur40_image_header {
 #define VIDEO_PACKET_SIZE  16384
 
 /* polling interval (ms) */
-#define POLL_INTERVAL 10
+#define POLL_INTERVAL 4
 
 /* maximum number of contacts FIXME: this is a guess? */
 #define MAX_CONTACTS 64
@@ -163,7 +164,7 @@ struct sur40_state {
 };
 
 struct sur40_buffer {
-       struct vb2_buffer vb;
+       struct vb2_v4l2_buffer vb;
        struct list_head list;
 };
 
@@ -342,7 +343,7 @@ static void sur40_poll(struct input_polled_dev *polldev)
                 * instead of at the end.
                 */
                if (packet_id != header->packet_id)
-                       dev_warn(sur40->dev, "packet ID mismatch\n");
+                       dev_dbg(sur40->dev, "packet ID mismatch\n");
 
                packet_blobs = result / sizeof(struct sur40_blob);
                dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
@@ -389,6 +390,8 @@ static void sur40_process_video(struct sur40_state *sur40)
        list_del(&new_buf->list);
        spin_unlock(&sur40->qlock);
 
+       dev_dbg(sur40->dev, "buffer acquired\n");
+
        /* retrieve data via bulk read */
        result = usb_bulk_msg(sur40->usbdev,
                        usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT),
@@ -416,7 +419,9 @@ static void sur40_process_video(struct sur40_state *sur40)
                goto err_poll;
        }
 
-       sgt = vb2_dma_sg_plane_desc(&new_buf->vb, 0);
+       dev_dbg(sur40->dev, "header acquired\n");
+
+       sgt = vb2_dma_sg_plane_desc(&new_buf->vb.vb2_buf, 0);
 
        result = usb_sg_init(&sgr, sur40->usbdev,
                usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
@@ -432,15 +437,22 @@ static void sur40_process_video(struct sur40_state *sur40)
                goto err_poll;
        }
 
+       dev_dbg(sur40->dev, "image acquired\n");
+
+       /* return error if streaming was stopped in the meantime */
+       if (sur40->sequence == -1)
+               goto err_poll;
+
        /* mark as finished */
-       v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
-       new_buf->vb.v4l2_buf.sequence = sur40->sequence++;
-       new_buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
-       vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+       v4l2_get_timestamp(&new_buf->vb.timestamp);
+       new_buf->vb.sequence = sur40->sequence++;
+       new_buf->vb.field = V4L2_FIELD_NONE;
+       vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+       dev_dbg(sur40->dev, "buffer marked done\n");
        return;
 
 err_poll:
-       vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_ERROR);
+       vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 }
 
 /* Initialize input device parameters. */
@@ -570,6 +582,7 @@ static int sur40_probe(struct usb_interface *interface,
        sur40->alloc_ctx = vb2_dma_sg_init_ctx(sur40->dev);
        if (IS_ERR(sur40->alloc_ctx)) {
                dev_err(sur40->dev, "Can't allocate buffer context");
+               error = PTR_ERR(sur40->alloc_ctx);
                goto err_unreg_v4l2;
        }
 
@@ -631,10 +644,11 @@ static void sur40_disconnect(struct usb_interface *interface)
  * minimum number: many DMA engines need a minimum of 2 buffers in the
  * queue and you need to have another available for userspace processing.
  */
-static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int sur40_queue_setup(struct vb2_queue *q, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct sur40_state *sur40 = vb2_get_drv_priv(q);
 
        if (q->num_buffers + *nbuffers < 3)
@@ -689,7 +703,7 @@ static void return_all_buffers(struct sur40_state *sur40,
 
        spin_lock(&sur40->qlock);
        list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
-               vb2_buffer_done(&buf->vb, state);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
                list_del(&buf->list);
        }
        spin_unlock(&sur40->qlock);
@@ -716,6 +730,7 @@ static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count)
 static void sur40_stop_streaming(struct vb2_queue *vq)
 {
        struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+       sur40->sequence = -1;
 
        /* Release all active buffers */
        return_all_buffers(sur40, VB2_BUF_STATE_ERROR);
@@ -778,6 +793,33 @@ static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
        return 0;
 }
 
+static int sur40_vidioc_enum_framesizes(struct file *file, void *priv,
+                                       struct v4l2_frmsizeenum *f)
+{
+       if ((f->index != 0) || (f->pixel_format != V4L2_PIX_FMT_GREY))
+               return -EINVAL;
+
+       f->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       f->discrete.width  = sur40_video_format.width;
+       f->discrete.height = sur40_video_format.height;
+       return 0;
+}
+
+static int sur40_vidioc_enum_frameintervals(struct file *file, void *priv,
+                                           struct v4l2_frmivalenum *f)
+{
+       if ((f->index > 1) || (f->pixel_format != V4L2_PIX_FMT_GREY)
+               || (f->width  != sur40_video_format.width)
+               || (f->height != sur40_video_format.height))
+                       return -EINVAL;
+
+       f->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       f->discrete.denominator  = 60/(f->index+1);
+       f->discrete.numerator = 1;
+       return 0;
+}
+
+
 static const struct usb_device_id sur40_table[] = {
        { USB_DEVICE(ID_MICROSOFT, ID_SUR40) },  /* Samsung SUR40 */
        { }                                      /* terminating null entry */
@@ -829,6 +871,9 @@ static const struct v4l2_ioctl_ops sur40_video_ioctl_ops = {
        .vidioc_s_fmt_vid_cap   = sur40_vidioc_fmt,
        .vidioc_g_fmt_vid_cap   = sur40_vidioc_fmt,
 
+       .vidioc_enum_framesizes = sur40_vidioc_enum_framesizes,
+       .vidioc_enum_frameintervals = sur40_vidioc_enum_frameintervals,
+
        .vidioc_enum_input      = sur40_vidioc_enum_input,
        .vidioc_g_input         = sur40_vidioc_g_input,
        .vidioc_s_input         = sur40_vidioc_s_input,