diff options
Diffstat (limited to 'drivers/media/platform/mem2mem_testdev.c')
-rw-r--r-- | drivers/media/platform/mem2mem_testdev.c | 95 |
1 files changed, 73 insertions, 22 deletions
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 08e24379b794..4f3096b17066 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c | |||
@@ -60,9 +60,7 @@ MODULE_PARM_DESC(debug, "activates debug info"); | |||
60 | #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024) | 60 | #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024) |
61 | 61 | ||
62 | /* Default transaction time in msec */ | 62 | /* Default transaction time in msec */ |
63 | #define MEM2MEM_DEF_TRANSTIME 1000 | 63 | #define MEM2MEM_DEF_TRANSTIME 40 |
64 | /* Default number of buffers per transaction */ | ||
65 | #define MEM2MEM_DEF_TRANSLEN 1 | ||
66 | #define MEM2MEM_COLOR_STEP (0xff >> 4) | 64 | #define MEM2MEM_COLOR_STEP (0xff >> 4) |
67 | #define MEM2MEM_NUM_TILES 8 | 65 | #define MEM2MEM_NUM_TILES 8 |
68 | 66 | ||
@@ -114,6 +112,7 @@ struct m2mtest_q_data { | |||
114 | unsigned int width; | 112 | unsigned int width; |
115 | unsigned int height; | 113 | unsigned int height; |
116 | unsigned int sizeimage; | 114 | unsigned int sizeimage; |
115 | unsigned int sequence; | ||
117 | struct m2mtest_fmt *fmt; | 116 | struct m2mtest_fmt *fmt; |
118 | }; | 117 | }; |
119 | 118 | ||
@@ -236,9 +235,21 @@ static int device_process(struct m2mtest_ctx *ctx, | |||
236 | bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES; | 235 | bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES; |
237 | w = 0; | 236 | w = 0; |
238 | 237 | ||
238 | out_vb->v4l2_buf.sequence = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; | ||
239 | in_vb->v4l2_buf.sequence = q_data->sequence++; | ||
239 | memcpy(&out_vb->v4l2_buf.timestamp, | 240 | memcpy(&out_vb->v4l2_buf.timestamp, |
240 | &in_vb->v4l2_buf.timestamp, | 241 | &in_vb->v4l2_buf.timestamp, |
241 | sizeof(struct timeval)); | 242 | sizeof(struct timeval)); |
243 | if (in_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TIMECODE) | ||
244 | memcpy(&out_vb->v4l2_buf.timecode, &in_vb->v4l2_buf.timecode, | ||
245 | sizeof(struct v4l2_timecode)); | ||
246 | out_vb->v4l2_buf.field = in_vb->v4l2_buf.field; | ||
247 | out_vb->v4l2_buf.flags = in_vb->v4l2_buf.flags & | ||
248 | (V4L2_BUF_FLAG_TIMECODE | | ||
249 | V4L2_BUF_FLAG_KEYFRAME | | ||
250 | V4L2_BUF_FLAG_PFRAME | | ||
251 | V4L2_BUF_FLAG_BFRAME | | ||
252 | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); | ||
242 | 253 | ||
243 | switch (ctx->mode) { | 254 | switch (ctx->mode) { |
244 | case MEM2MEM_HFLIP | MEM2MEM_VFLIP: | 255 | case MEM2MEM_HFLIP | MEM2MEM_VFLIP: |
@@ -505,19 +516,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
505 | 516 | ||
506 | static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) | 517 | static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) |
507 | { | 518 | { |
508 | enum v4l2_field field; | ||
509 | |||
510 | field = f->fmt.pix.field; | ||
511 | |||
512 | if (field == V4L2_FIELD_ANY) | ||
513 | field = V4L2_FIELD_NONE; | ||
514 | else if (V4L2_FIELD_NONE != field) | ||
515 | return -EINVAL; | ||
516 | |||
517 | /* V4L2 specification suggests the driver corrects the format struct | 519 | /* V4L2 specification suggests the driver corrects the format struct |
518 | * if any of the dimensions is unsupported */ | 520 | * if any of the dimensions is unsupported */ |
519 | f->fmt.pix.field = field; | ||
520 | |||
521 | if (f->fmt.pix.height < MIN_H) | 521 | if (f->fmt.pix.height < MIN_H) |
522 | f->fmt.pix.height = MIN_H; | 522 | f->fmt.pix.height = MIN_H; |
523 | else if (f->fmt.pix.height > MAX_H) | 523 | else if (f->fmt.pix.height > MAX_H) |
@@ -531,6 +531,8 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) | |||
531 | f->fmt.pix.width &= ~DIM_ALIGN_MASK; | 531 | f->fmt.pix.width &= ~DIM_ALIGN_MASK; |
532 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | 532 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; |
533 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 533 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
534 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
535 | f->fmt.pix.priv = 0; | ||
534 | 536 | ||
535 | return 0; | 537 | return 0; |
536 | } | 538 | } |
@@ -542,7 +544,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
542 | struct m2mtest_ctx *ctx = file2ctx(file); | 544 | struct m2mtest_ctx *ctx = file2ctx(file); |
543 | 545 | ||
544 | fmt = find_format(f); | 546 | fmt = find_format(f); |
545 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { | 547 | if (!fmt) { |
548 | f->fmt.pix.pixelformat = formats[0].fourcc; | ||
549 | fmt = find_format(f); | ||
550 | } | ||
551 | if (!(fmt->types & MEM2MEM_CAPTURE)) { | ||
546 | v4l2_err(&ctx->dev->v4l2_dev, | 552 | v4l2_err(&ctx->dev->v4l2_dev, |
547 | "Fourcc format (0x%08x) invalid.\n", | 553 | "Fourcc format (0x%08x) invalid.\n", |
548 | f->fmt.pix.pixelformat); | 554 | f->fmt.pix.pixelformat); |
@@ -560,7 +566,11 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, | |||
560 | struct m2mtest_ctx *ctx = file2ctx(file); | 566 | struct m2mtest_ctx *ctx = file2ctx(file); |
561 | 567 | ||
562 | fmt = find_format(f); | 568 | fmt = find_format(f); |
563 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { | 569 | if (!fmt) { |
570 | f->fmt.pix.pixelformat = formats[0].fourcc; | ||
571 | fmt = find_format(f); | ||
572 | } | ||
573 | if (!(fmt->types & MEM2MEM_OUTPUT)) { | ||
564 | v4l2_err(&ctx->dev->v4l2_dev, | 574 | v4l2_err(&ctx->dev->v4l2_dev, |
565 | "Fourcc format (0x%08x) invalid.\n", | 575 | "Fourcc format (0x%08x) invalid.\n", |
566 | f->fmt.pix.pixelformat); | 576 | f->fmt.pix.pixelformat); |
@@ -740,6 +750,15 @@ static int m2mtest_buf_prepare(struct vb2_buffer *vb) | |||
740 | dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); | 750 | dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); |
741 | 751 | ||
742 | q_data = get_q_data(ctx, vb->vb2_queue->type); | 752 | q_data = get_q_data(ctx, vb->vb2_queue->type); |
753 | if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { | ||
754 | if (vb->v4l2_buf.field == V4L2_FIELD_ANY) | ||
755 | vb->v4l2_buf.field = V4L2_FIELD_NONE; | ||
756 | if (vb->v4l2_buf.field != V4L2_FIELD_NONE) { | ||
757 | dprintk(ctx->dev, "%s field isn't supported\n", | ||
758 | __func__); | ||
759 | return -EINVAL; | ||
760 | } | ||
761 | } | ||
743 | 762 | ||
744 | if (vb2_plane_size(vb, 0) < q_data->sizeimage) { | 763 | if (vb2_plane_size(vb, 0) < q_data->sizeimage) { |
745 | dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n", | 764 | dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n", |
@@ -755,13 +774,45 @@ static int m2mtest_buf_prepare(struct vb2_buffer *vb) | |||
755 | static void m2mtest_buf_queue(struct vb2_buffer *vb) | 774 | static void m2mtest_buf_queue(struct vb2_buffer *vb) |
756 | { | 775 | { |
757 | struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | 776 | struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); |
777 | |||
758 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); | 778 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb); |
759 | } | 779 | } |
760 | 780 | ||
781 | static int m2mtest_start_streaming(struct vb2_queue *q, unsigned count) | ||
782 | { | ||
783 | struct m2mtest_ctx *ctx = vb2_get_drv_priv(q); | ||
784 | struct m2mtest_q_data *q_data = get_q_data(ctx, q->type); | ||
785 | |||
786 | q_data->sequence = 0; | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static int m2mtest_stop_streaming(struct vb2_queue *q) | ||
791 | { | ||
792 | struct m2mtest_ctx *ctx = vb2_get_drv_priv(q); | ||
793 | struct vb2_buffer *vb; | ||
794 | unsigned long flags; | ||
795 | |||
796 | for (;;) { | ||
797 | if (V4L2_TYPE_IS_OUTPUT(q->type)) | ||
798 | vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | ||
799 | else | ||
800 | vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); | ||
801 | if (vb == NULL) | ||
802 | return 0; | ||
803 | spin_lock_irqsave(&ctx->dev->irqlock, flags); | ||
804 | v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); | ||
805 | spin_unlock_irqrestore(&ctx->dev->irqlock, flags); | ||
806 | } | ||
807 | return 0; | ||
808 | } | ||
809 | |||
761 | static struct vb2_ops m2mtest_qops = { | 810 | static struct vb2_ops m2mtest_qops = { |
762 | .queue_setup = m2mtest_queue_setup, | 811 | .queue_setup = m2mtest_queue_setup, |
763 | .buf_prepare = m2mtest_buf_prepare, | 812 | .buf_prepare = m2mtest_buf_prepare, |
764 | .buf_queue = m2mtest_buf_queue, | 813 | .buf_queue = m2mtest_buf_queue, |
814 | .start_streaming = m2mtest_start_streaming, | ||
815 | .stop_streaming = m2mtest_stop_streaming, | ||
765 | .wait_prepare = vb2_ops_wait_prepare, | 816 | .wait_prepare = vb2_ops_wait_prepare, |
766 | .wait_finish = vb2_ops_wait_finish, | 817 | .wait_finish = vb2_ops_wait_finish, |
767 | }; | 818 | }; |
@@ -772,12 +823,12 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds | |||
772 | int ret; | 823 | int ret; |
773 | 824 | ||
774 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 825 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
775 | src_vq->io_modes = VB2_MMAP | VB2_DMABUF; | 826 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
776 | src_vq->drv_priv = ctx; | 827 | src_vq->drv_priv = ctx; |
777 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | 828 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); |
778 | src_vq->ops = &m2mtest_qops; | 829 | src_vq->ops = &m2mtest_qops; |
779 | src_vq->mem_ops = &vb2_vmalloc_memops; | 830 | src_vq->mem_ops = &vb2_vmalloc_memops; |
780 | src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; | 831 | src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
781 | src_vq->lock = &ctx->dev->dev_mutex; | 832 | src_vq->lock = &ctx->dev->dev_mutex; |
782 | 833 | ||
783 | ret = vb2_queue_init(src_vq); | 834 | ret = vb2_queue_init(src_vq); |
@@ -785,12 +836,12 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds | |||
785 | return ret; | 836 | return ret; |
786 | 837 | ||
787 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 838 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
788 | dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; | 839 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
789 | dst_vq->drv_priv = ctx; | 840 | dst_vq->drv_priv = ctx; |
790 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | 841 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); |
791 | dst_vq->ops = &m2mtest_qops; | 842 | dst_vq->ops = &m2mtest_qops; |
792 | dst_vq->mem_ops = &vb2_vmalloc_memops; | 843 | dst_vq->mem_ops = &vb2_vmalloc_memops; |
793 | dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; | 844 | dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; |
794 | dst_vq->lock = &ctx->dev->dev_mutex; | 845 | dst_vq->lock = &ctx->dev->dev_mutex; |
795 | 846 | ||
796 | return vb2_queue_init(dst_vq); | 847 | return vb2_queue_init(dst_vq); |
@@ -801,10 +852,10 @@ static const struct v4l2_ctrl_config m2mtest_ctrl_trans_time_msec = { | |||
801 | .id = V4L2_CID_TRANS_TIME_MSEC, | 852 | .id = V4L2_CID_TRANS_TIME_MSEC, |
802 | .name = "Transaction Time (msec)", | 853 | .name = "Transaction Time (msec)", |
803 | .type = V4L2_CTRL_TYPE_INTEGER, | 854 | .type = V4L2_CTRL_TYPE_INTEGER, |
804 | .def = 1001, | 855 | .def = MEM2MEM_DEF_TRANSTIME, |
805 | .min = 1, | 856 | .min = 1, |
806 | .max = 10001, | 857 | .max = 10001, |
807 | .step = 100, | 858 | .step = 1, |
808 | }; | 859 | }; |
809 | 860 | ||
810 | static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = { | 861 | static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = { |