Lines Matching +full:video +full:- +full:mem
1 // SPDX-License-Identifier: GPL-2.0+
3 * vsp1_video.c -- R-Car VSP1 Video Node
5 * Copyright (C) 2013-2015 Renesas Electronics Corporation
14 #include <linux/v4l2-mediabus.h>
18 #include <media/media-entity.h>
19 #include <media/v4l2-dev.h>
20 #include <media/v4l2-fh.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-subdev.h>
23 #include <media/videobuf2-v4l2.h>
24 #include <media/videobuf2-dma-contig.h>
44 /* -----------------------------------------------------------------------------
54 if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) in vsp1_video_remote_subdev()
58 *pad = remote->index; in vsp1_video_remote_subdev()
60 return media_entity_to_v4l2_subdev(remote->entity); in vsp1_video_remote_subdev()
63 static int vsp1_video_verify_format(struct vsp1_video *video) in vsp1_video_verify_format() argument
71 subdev = vsp1_video_remote_subdev(&video->pad, &fmt.pad); in vsp1_video_verify_format()
73 return -EINVAL; in vsp1_video_verify_format()
77 return ret == -ENOIOCTLCMD ? -EINVAL : ret; in vsp1_video_verify_format()
79 if (video->rwpf->fmtinfo->mbus != fmt.format.code || in vsp1_video_verify_format()
80 video->rwpf->format.height != fmt.format.height || in vsp1_video_verify_format()
81 video->rwpf->format.width != fmt.format.width) { in vsp1_video_verify_format()
82 dev_dbg(video->vsp1->dev, in vsp1_video_verify_format()
84 video->rwpf->fmtinfo->mbus, video->rwpf->format.width, in vsp1_video_verify_format()
85 video->rwpf->format.height, fmt.format.code, in vsp1_video_verify_format()
87 return -EPIPE; in vsp1_video_verify_format()
93 static int __vsp1_video_try_format(struct vsp1_video *video, in __vsp1_video_try_format() argument
105 unsigned int width = pix->width; in __vsp1_video_try_format()
106 unsigned int height = pix->height; in __vsp1_video_try_format()
115 if (xrgb_formats[i][0] == pix->pixelformat) { in __vsp1_video_try_format()
116 pix->pixelformat = xrgb_formats[i][1]; in __vsp1_video_try_format()
125 info = vsp1_get_format_info(video->vsp1, pix->pixelformat); in __vsp1_video_try_format()
127 info = vsp1_get_format_info(video->vsp1, VSP1_VIDEO_DEF_FORMAT); in __vsp1_video_try_format()
129 pix->pixelformat = info->fourcc; in __vsp1_video_try_format()
130 pix->colorspace = V4L2_COLORSPACE_SRGB; in __vsp1_video_try_format()
131 pix->field = V4L2_FIELD_NONE; in __vsp1_video_try_format()
133 if (info->fourcc == V4L2_PIX_FMT_HSV24 || in __vsp1_video_try_format()
134 info->fourcc == V4L2_PIX_FMT_HSV32) in __vsp1_video_try_format()
135 pix->hsv_enc = V4L2_HSV_ENC_256; in __vsp1_video_try_format()
137 memset(pix->reserved, 0, sizeof(pix->reserved)); in __vsp1_video_try_format()
140 width = round_down(width, info->hsub); in __vsp1_video_try_format()
141 height = round_down(height, info->vsub); in __vsp1_video_try_format()
144 pix->width = clamp(width, info->hsub, VSP1_VIDEO_MAX_WIDTH); in __vsp1_video_try_format()
145 pix->height = clamp(height, info->vsub, VSP1_VIDEO_MAX_HEIGHT); in __vsp1_video_try_format()
152 for (i = 0; i < min(info->planes, 2U); ++i) { in __vsp1_video_try_format()
153 unsigned int hsub = i > 0 ? info->hsub : 1; in __vsp1_video_try_format()
154 unsigned int vsub = i > 0 ? info->vsub : 1; in __vsp1_video_try_format()
158 bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline, in __vsp1_video_try_format()
159 pix->width / hsub * info->bpp[i] / 8, in __vsp1_video_try_format()
162 pix->plane_fmt[i].bytesperline = round_up(bpl, align); in __vsp1_video_try_format()
163 pix->plane_fmt[i].sizeimage = pix->plane_fmt[i].bytesperline in __vsp1_video_try_format()
164 * pix->height / vsub; in __vsp1_video_try_format()
167 if (info->planes == 3) { in __vsp1_video_try_format()
169 pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline; in __vsp1_video_try_format()
170 pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage; in __vsp1_video_try_format()
173 pix->num_planes = info->planes; in __vsp1_video_try_format()
181 /* -----------------------------------------------------------------------------
186 * vsp1_video_complete_buffer - Complete the current buffer
187 * @video: the video node
195 vsp1_video_complete_buffer(struct vsp1_video *video) in vsp1_video_complete_buffer() argument
197 struct vsp1_pipeline *pipe = video->rwpf->entity.pipe; in vsp1_video_complete_buffer()
203 spin_lock_irqsave(&video->irqlock, flags); in vsp1_video_complete_buffer()
205 if (list_empty(&video->irqqueue)) { in vsp1_video_complete_buffer()
206 spin_unlock_irqrestore(&video->irqlock, flags); in vsp1_video_complete_buffer()
210 done = list_first_entry(&video->irqqueue, in vsp1_video_complete_buffer()
213 list_del(&done->queue); in vsp1_video_complete_buffer()
215 if (!list_empty(&video->irqqueue)) in vsp1_video_complete_buffer()
216 next = list_first_entry(&video->irqqueue, in vsp1_video_complete_buffer()
219 spin_unlock_irqrestore(&video->irqlock, flags); in vsp1_video_complete_buffer()
221 done->buf.sequence = pipe->sequence; in vsp1_video_complete_buffer()
222 done->buf.vb2_buf.timestamp = ktime_get_ns(); in vsp1_video_complete_buffer()
223 for (i = 0; i < done->buf.vb2_buf.num_planes; ++i) in vsp1_video_complete_buffer()
224 vb2_set_plane_payload(&done->buf.vb2_buf, i, in vsp1_video_complete_buffer()
225 vb2_plane_size(&done->buf.vb2_buf, i)); in vsp1_video_complete_buffer()
226 vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE); in vsp1_video_complete_buffer()
234 struct vsp1_video *video = rwpf->video; in vsp1_video_frame_end() local
237 buf = vsp1_video_complete_buffer(video); in vsp1_video_frame_end()
241 video->rwpf->mem = buf->mem; in vsp1_video_frame_end()
242 pipe->buffers_ready |= 1 << video->pipe_index; in vsp1_video_frame_end()
249 struct vsp1_partition *part = &pipe->part_table[partition]; in vsp1_video_pipeline_run_partition()
253 list_for_each_entry(entity, &pipe->entities, list_pipe) in vsp1_video_pipeline_run_partition()
259 struct vsp1_device *vsp1 = pipe->output->entity.vsp1; in vsp1_video_pipeline_run()
265 dl = vsp1_dl_list_get(pipe->output->dlm); in vsp1_video_pipeline_run()
273 if (!pipe->configured) in vsp1_video_pipeline_run()
274 vsp1_dl_list_add_body(dl, pipe->stream_config); in vsp1_video_pipeline_run()
278 list_for_each_entry(entity, &pipe->entities, list_pipe) in vsp1_video_pipeline_run()
285 for (partition = 1; partition < pipe->partitions; ++partition) { in vsp1_video_pipeline_run()
288 dl_next = vsp1_dl_list_get(pipe->output->dlm); in vsp1_video_pipeline_run()
296 dev_err(vsp1->dev, "Failed to obtain a dl list. Frame will be incomplete\n"); in vsp1_video_pipeline_run()
306 pipe->configured = true; in vsp1_video_pipeline_run()
314 struct vsp1_device *vsp1 = pipe->output->entity.vsp1; in vsp1_video_pipeline_frame_end()
322 spin_lock_irqsave(&pipe->irqlock, flags); in vsp1_video_pipeline_frame_end()
324 /* Complete buffers on all video nodes. */ in vsp1_video_pipeline_frame_end()
325 for (i = 0; i < vsp1->info->rpf_count; ++i) { in vsp1_video_pipeline_frame_end()
326 if (!pipe->inputs[i]) in vsp1_video_pipeline_frame_end()
329 vsp1_video_frame_end(pipe, pipe->inputs[i]); in vsp1_video_pipeline_frame_end()
332 vsp1_video_frame_end(pipe, pipe->output); in vsp1_video_pipeline_frame_end()
334 state = pipe->state; in vsp1_video_pipeline_frame_end()
335 pipe->state = VSP1_PIPELINE_STOPPED; in vsp1_video_pipeline_frame_end()
342 wake_up(&pipe->wq); in vsp1_video_pipeline_frame_end()
346 spin_unlock_irqrestore(&pipe->irqlock, flags); in vsp1_video_pipeline_frame_end()
359 ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev); in vsp1_video_pipeline_build_branch()
368 pad = vsp1_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); in vsp1_video_pipeline_build_branch()
372 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
376 /* We've reached a video node, that shouldn't have happened. */ in vsp1_video_pipeline_build_branch()
377 if (!is_media_entity_v4l2_subdev(pad->entity)) { in vsp1_video_pipeline_build_branch()
378 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
383 media_entity_to_v4l2_subdev(pad->entity)); in vsp1_video_pipeline_build_branch()
389 if (entity->type == VSP1_ENTITY_BRU || in vsp1_video_pipeline_build_branch()
390 entity->type == VSP1_ENTITY_BRS) { in vsp1_video_pipeline_build_branch()
393 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
397 brx = to_brx(&entity->subdev); in vsp1_video_pipeline_build_branch()
398 brx->inputs[pad->index].rpf = input; in vsp1_video_pipeline_build_branch()
399 input->brx_input = pad->index; in vsp1_video_pipeline_build_branch()
403 if (entity->type == VSP1_ENTITY_WPF) in vsp1_video_pipeline_build_branch()
408 &entity->subdev.entity)) { in vsp1_video_pipeline_build_branch()
409 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
414 if (entity->type == VSP1_ENTITY_UDS) { in vsp1_video_pipeline_build_branch()
415 if (pipe->uds) { in vsp1_video_pipeline_build_branch()
416 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
420 pipe->uds = entity; in vsp1_video_pipeline_build_branch()
421 pipe->uds_input = brx ? &brx->entity : &input->entity; in vsp1_video_pipeline_build_branch()
425 pad = &entity->pads[entity->source_pad]; in vsp1_video_pipeline_build_branch()
430 if (entity != &output->entity) in vsp1_video_pipeline_build_branch()
431 ret = -EPIPE; in vsp1_video_pipeline_build_branch()
440 struct vsp1_video *video) in vsp1_video_pipeline_build() argument
443 struct media_entity *entity = &video->video.entity; in vsp1_video_pipeline_build()
444 struct media_device *mdev = entity->graph_obj.mdev; in vsp1_video_pipeline_build()
448 /* Walk the graph to locate the entities and video nodes. */ in vsp1_video_pipeline_build()
465 list_add_tail(&e->list_pipe, &pipe->entities); in vsp1_video_pipeline_build()
466 e->pipe = pipe; in vsp1_video_pipeline_build()
468 switch (e->type) { in vsp1_video_pipeline_build()
471 pipe->inputs[rwpf->entity.index] = rwpf; in vsp1_video_pipeline_build()
472 rwpf->video->pipe_index = ++pipe->num_inputs; in vsp1_video_pipeline_build()
477 pipe->output = rwpf; in vsp1_video_pipeline_build()
478 rwpf->video->pipe_index = 0; in vsp1_video_pipeline_build()
482 pipe->lif = e; in vsp1_video_pipeline_build()
487 pipe->brx = e; in vsp1_video_pipeline_build()
491 pipe->hgo = e; in vsp1_video_pipeline_build()
495 pipe->hgt = e; in vsp1_video_pipeline_build()
506 if (pipe->num_inputs == 0 || !pipe->output) in vsp1_video_pipeline_build()
507 return -EPIPE; in vsp1_video_pipeline_build()
513 for (i = 0; i < video->vsp1->info->rpf_count; ++i) { in vsp1_video_pipeline_build()
514 if (!pipe->inputs[i]) in vsp1_video_pipeline_build()
517 ret = vsp1_video_pipeline_build_branch(pipe, pipe->inputs[i], in vsp1_video_pipeline_build()
518 pipe->output); in vsp1_video_pipeline_build()
527 struct vsp1_video *video) in vsp1_video_pipeline_init() argument
533 pipe->frame_end = vsp1_video_pipeline_frame_end; in vsp1_video_pipeline_init()
535 ret = vsp1_video_pipeline_build(pipe, video); in vsp1_video_pipeline_init()
539 vsp1_pipeline_dump(pipe, "video"); in vsp1_video_pipeline_init()
544 static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video) in vsp1_video_pipeline_get() argument
550 * Get a pipeline object for the video node. If a pipeline has already in vsp1_video_pipeline_get()
555 if (!video->rwpf->entity.pipe) { in vsp1_video_pipeline_get()
558 return ERR_PTR(-ENOMEM); in vsp1_video_pipeline_get()
560 ret = vsp1_video_pipeline_init(pipe, video); in vsp1_video_pipeline_get()
567 pipe = video->rwpf->entity.pipe; in vsp1_video_pipeline_get()
568 kref_get(&pipe->kref); in vsp1_video_pipeline_get()
584 struct media_device *mdev = &pipe->output->entity.vsp1->media_dev; in vsp1_video_pipeline_put()
586 mutex_lock(&mdev->graph_mutex); in vsp1_video_pipeline_put()
587 kref_put(&pipe->kref, vsp1_video_pipeline_release); in vsp1_video_pipeline_put()
588 mutex_unlock(&mdev->graph_mutex); in vsp1_video_pipeline_put()
591 /* -----------------------------------------------------------------------------
600 struct vsp1_video *video = vb2_get_drv_priv(vq); in vsp1_video_queue_setup() local
601 const struct v4l2_pix_format_mplane *format = &video->rwpf->format; in vsp1_video_queue_setup()
605 if (*nplanes != format->num_planes) in vsp1_video_queue_setup()
606 return -EINVAL; in vsp1_video_queue_setup()
609 if (sizes[i] < format->plane_fmt[i].sizeimage) in vsp1_video_queue_setup()
610 return -EINVAL; in vsp1_video_queue_setup()
614 *nplanes = format->num_planes; in vsp1_video_queue_setup()
616 for (i = 0; i < format->num_planes; ++i) in vsp1_video_queue_setup()
617 sizes[i] = format->plane_fmt[i].sizeimage; in vsp1_video_queue_setup()
625 struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); in vsp1_video_buffer_prepare() local
627 const struct v4l2_pix_format_mplane *format = &video->rwpf->format; in vsp1_video_buffer_prepare()
630 if (vb->num_planes < format->num_planes) in vsp1_video_buffer_prepare()
631 return -EINVAL; in vsp1_video_buffer_prepare()
633 for (i = 0; i < vb->num_planes; ++i) { in vsp1_video_buffer_prepare()
634 buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); in vsp1_video_buffer_prepare()
636 if (vb2_plane_size(vb, i) < format->plane_fmt[i].sizeimage) in vsp1_video_buffer_prepare()
637 return -EINVAL; in vsp1_video_buffer_prepare()
641 buf->mem.addr[i] = 0; in vsp1_video_buffer_prepare()
649 struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); in vsp1_video_buffer_queue() local
650 struct vsp1_pipeline *pipe = video->rwpf->entity.pipe; in vsp1_video_buffer_queue()
655 spin_lock_irqsave(&video->irqlock, flags); in vsp1_video_buffer_queue()
656 empty = list_empty(&video->irqqueue); in vsp1_video_buffer_queue()
657 list_add_tail(&buf->queue, &video->irqqueue); in vsp1_video_buffer_queue()
658 spin_unlock_irqrestore(&video->irqlock, flags); in vsp1_video_buffer_queue()
663 spin_lock_irqsave(&pipe->irqlock, flags); in vsp1_video_buffer_queue()
665 video->rwpf->mem = buf->mem; in vsp1_video_buffer_queue()
666 pipe->buffers_ready |= 1 << video->pipe_index; in vsp1_video_buffer_queue()
668 if (vb2_start_streaming_called(&video->queue) && in vsp1_video_buffer_queue()
672 spin_unlock_irqrestore(&pipe->irqlock, flags); in vsp1_video_buffer_queue()
677 struct vsp1_device *vsp1 = pipe->output->entity.vsp1; in vsp1_video_pipeline_setup_partitions()
687 format = v4l2_subdev_state_get_format(pipe->output->entity.state, in vsp1_video_pipeline_setup_partitions()
689 div_size = format->width; in vsp1_video_pipeline_setup_partitions()
695 if (vsp1->info->gen >= 3) { in vsp1_video_pipeline_setup_partitions()
696 list_for_each_entry(entity, &pipe->entities, list_pipe) { in vsp1_video_pipeline_setup_partitions()
699 if (!entity->ops->max_width) in vsp1_video_pipeline_setup_partitions()
702 entity_max = entity->ops->max_width(entity, in vsp1_video_pipeline_setup_partitions()
703 entity->state, in vsp1_video_pipeline_setup_partitions()
710 pipe->partitions = DIV_ROUND_UP(format->width, div_size); in vsp1_video_pipeline_setup_partitions()
711 pipe->part_table = kcalloc(pipe->partitions, sizeof(*pipe->part_table), in vsp1_video_pipeline_setup_partitions()
713 if (!pipe->part_table) in vsp1_video_pipeline_setup_partitions()
714 return -ENOMEM; in vsp1_video_pipeline_setup_partitions()
716 for (i = 0; i < pipe->partitions; ++i) in vsp1_video_pipeline_setup_partitions()
717 vsp1_pipeline_calculate_partition(pipe, &pipe->part_table[i], in vsp1_video_pipeline_setup_partitions()
733 if (pipe->uds) { in vsp1_video_setup_pipeline()
734 struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); in vsp1_video_setup_pipeline()
743 if (pipe->uds_input->type == VSP1_ENTITY_BRU || in vsp1_video_setup_pipeline()
744 pipe->uds_input->type == VSP1_ENTITY_BRS) { in vsp1_video_setup_pipeline()
745 uds->scale_alpha = false; in vsp1_video_setup_pipeline()
748 to_rwpf(&pipe->uds_input->subdev); in vsp1_video_setup_pipeline()
750 uds->scale_alpha = rpf->fmtinfo->alpha; in vsp1_video_setup_pipeline()
759 pipe->stream_config = vsp1_dlm_dl_body_get(pipe->output->dlm); in vsp1_video_setup_pipeline()
760 if (!pipe->stream_config) in vsp1_video_setup_pipeline()
761 return -ENOMEM; in vsp1_video_setup_pipeline()
763 list_for_each_entry(entity, &pipe->entities, list_pipe) { in vsp1_video_setup_pipeline()
764 vsp1_entity_route_setup(entity, pipe, pipe->stream_config); in vsp1_video_setup_pipeline()
765 vsp1_entity_configure_stream(entity, entity->state, pipe, NULL, in vsp1_video_setup_pipeline()
766 pipe->stream_config); in vsp1_video_setup_pipeline()
772 static void vsp1_video_release_buffers(struct vsp1_video *video) in vsp1_video_release_buffers() argument
778 spin_lock_irqsave(&video->irqlock, flags); in vsp1_video_release_buffers()
779 list_for_each_entry(buffer, &video->irqqueue, queue) in vsp1_video_release_buffers()
780 vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR); in vsp1_video_release_buffers()
781 INIT_LIST_HEAD(&video->irqqueue); in vsp1_video_release_buffers()
782 spin_unlock_irqrestore(&video->irqlock, flags); in vsp1_video_release_buffers()
787 lockdep_assert_held(&pipe->lock); in vsp1_video_cleanup_pipeline()
789 /* Release any cached configuration from our output video. */ in vsp1_video_cleanup_pipeline()
790 vsp1_dl_body_put(pipe->stream_config); in vsp1_video_cleanup_pipeline()
791 pipe->stream_config = NULL; in vsp1_video_cleanup_pipeline()
792 pipe->configured = false; in vsp1_video_cleanup_pipeline()
795 kfree(pipe->part_table); in vsp1_video_cleanup_pipeline()
796 pipe->part_table = NULL; in vsp1_video_cleanup_pipeline()
801 struct vsp1_video *video = vb2_get_drv_priv(vq); in vsp1_video_start_streaming() local
802 struct vsp1_pipeline *pipe = video->rwpf->entity.pipe; in vsp1_video_start_streaming()
807 mutex_lock(&pipe->lock); in vsp1_video_start_streaming()
808 if (pipe->stream_count == pipe->num_inputs) { in vsp1_video_start_streaming()
811 vsp1_video_release_buffers(video); in vsp1_video_start_streaming()
813 mutex_unlock(&pipe->lock); in vsp1_video_start_streaming()
820 pipe->stream_count++; in vsp1_video_start_streaming()
821 mutex_unlock(&pipe->lock); in vsp1_video_start_streaming()
833 spin_lock_irqsave(&pipe->irqlock, flags); in vsp1_video_start_streaming()
836 spin_unlock_irqrestore(&pipe->irqlock, flags); in vsp1_video_start_streaming()
843 struct vsp1_video *video = vb2_get_drv_priv(vq); in vsp1_video_stop_streaming() local
844 struct vsp1_pipeline *pipe = video->rwpf->entity.pipe; in vsp1_video_stop_streaming()
850 * by a QBUF on the video node on the other side of the pipeline. in vsp1_video_stop_streaming()
852 spin_lock_irqsave(&video->irqlock, flags); in vsp1_video_stop_streaming()
853 pipe->buffers_ready &= ~(1 << video->pipe_index); in vsp1_video_stop_streaming()
854 spin_unlock_irqrestore(&video->irqlock, flags); in vsp1_video_stop_streaming()
856 mutex_lock(&pipe->lock); in vsp1_video_stop_streaming()
857 if (--pipe->stream_count == pipe->num_inputs) { in vsp1_video_stop_streaming()
860 if (ret == -ETIMEDOUT) in vsp1_video_stop_streaming()
861 dev_err(video->vsp1->dev, "pipeline stop timeout\n"); in vsp1_video_stop_streaming()
865 mutex_unlock(&pipe->lock); in vsp1_video_stop_streaming()
867 video_device_pipeline_stop(&video->video); in vsp1_video_stop_streaming()
868 vsp1_video_release_buffers(video); in vsp1_video_stop_streaming()
882 /* -----------------------------------------------------------------------------
889 struct v4l2_fh *vfh = file->private_data; in vsp1_video_querycap()
890 struct vsp1_video *video = to_vsp1_video(vfh->vdev); in vsp1_video_querycap() local
892 cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING in vsp1_video_querycap()
897 strscpy(cap->driver, "vsp1", sizeof(cap->driver)); in vsp1_video_querycap()
898 strscpy(cap->card, video->video.name, sizeof(cap->card)); in vsp1_video_querycap()
906 struct v4l2_fh *vfh = file->private_data; in vsp1_video_get_format()
907 struct vsp1_video *video = to_vsp1_video(vfh->vdev); in vsp1_video_get_format() local
909 if (format->type != video->queue.type) in vsp1_video_get_format()
910 return -EINVAL; in vsp1_video_get_format()
912 mutex_lock(&video->lock); in vsp1_video_get_format()
913 format->fmt.pix_mp = video->rwpf->format; in vsp1_video_get_format()
914 mutex_unlock(&video->lock); in vsp1_video_get_format()
922 struct v4l2_fh *vfh = file->private_data; in vsp1_video_try_format()
923 struct vsp1_video *video = to_vsp1_video(vfh->vdev); in vsp1_video_try_format() local
925 if (format->type != video->queue.type) in vsp1_video_try_format()
926 return -EINVAL; in vsp1_video_try_format()
928 return __vsp1_video_try_format(video, &format->fmt.pix_mp, NULL); in vsp1_video_try_format()
934 struct v4l2_fh *vfh = file->private_data; in vsp1_video_set_format()
935 struct vsp1_video *video = to_vsp1_video(vfh->vdev); in vsp1_video_set_format() local
939 if (format->type != video->queue.type) in vsp1_video_set_format()
940 return -EINVAL; in vsp1_video_set_format()
942 ret = __vsp1_video_try_format(video, &format->fmt.pix_mp, &info); in vsp1_video_set_format()
946 mutex_lock(&video->lock); in vsp1_video_set_format()
948 if (vb2_is_busy(&video->queue)) { in vsp1_video_set_format()
949 ret = -EBUSY; in vsp1_video_set_format()
953 video->rwpf->format = format->fmt.pix_mp; in vsp1_video_set_format()
954 video->rwpf->fmtinfo = info; in vsp1_video_set_format()
957 mutex_unlock(&video->lock); in vsp1_video_set_format()
964 struct v4l2_fh *vfh = file->private_data; in vsp1_video_streamon()
965 struct vsp1_video *video = to_vsp1_video(vfh->vdev); in vsp1_video_streamon() local
966 struct media_device *mdev = &video->vsp1->media_dev; in vsp1_video_streamon()
970 if (vb2_queue_is_busy(&video->queue, file)) in vsp1_video_streamon()
971 return -EBUSY; in vsp1_video_streamon()
974 * Get a pipeline for the video node and start streaming on it. No link in vsp1_video_streamon()
978 mutex_lock(&mdev->graph_mutex); in vsp1_video_streamon()
980 pipe = vsp1_video_pipeline_get(video); in vsp1_video_streamon()
982 mutex_unlock(&mdev->graph_mutex); in vsp1_video_streamon()
986 ret = __video_device_pipeline_start(&video->video, &pipe->pipe); in vsp1_video_streamon()
988 mutex_unlock(&mdev->graph_mutex); in vsp1_video_streamon()
992 mutex_unlock(&mdev->graph_mutex); in vsp1_video_streamon()
998 ret = vsp1_video_verify_format(video); in vsp1_video_streamon()
1003 ret = vb2_streamon(&video->queue, type); in vsp1_video_streamon()
1010 video_device_pipeline_stop(&video->video); in vsp1_video_streamon()
1035 /* -----------------------------------------------------------------------------
1041 struct vsp1_video *video = video_drvdata(file); in vsp1_video_open() local
1047 return -ENOMEM; in vsp1_video_open()
1049 v4l2_fh_init(vfh, &video->video); in vsp1_video_open()
1052 file->private_data = vfh; in vsp1_video_open()
1054 ret = vsp1_device_get(video->vsp1); in vsp1_video_open()
1066 struct vsp1_video *video = video_drvdata(file); in vsp1_video_release() local
1070 vsp1_device_put(video->vsp1); in vsp1_video_release()
1084 /* -----------------------------------------------------------------------------
1093 * manually. That would however break userspace that start one video in vsp1_video_link_validate()
1094 * device before configures formats on other video devices in the in vsp1_video_link_validate()
1095 * pipeline. This operation is just a no-op to silence the warnings in vsp1_video_link_validate()
1105 /* -----------------------------------------------------------------------------
1120 for (i = 0; i < vsp1->info->wpf_count; ++i) { in vsp1_video_suspend()
1121 struct vsp1_rwpf *wpf = vsp1->wpf[i]; in vsp1_video_suspend()
1127 pipe = wpf->entity.pipe; in vsp1_video_suspend()
1131 spin_lock_irqsave(&pipe->irqlock, flags); in vsp1_video_suspend()
1132 if (pipe->state == VSP1_PIPELINE_RUNNING) in vsp1_video_suspend()
1133 pipe->state = VSP1_PIPELINE_STOPPING; in vsp1_video_suspend()
1134 spin_unlock_irqrestore(&pipe->irqlock, flags); in vsp1_video_suspend()
1137 for (i = 0; i < vsp1->info->wpf_count; ++i) { in vsp1_video_suspend()
1138 struct vsp1_rwpf *wpf = vsp1->wpf[i]; in vsp1_video_suspend()
1144 pipe = wpf->entity.pipe; in vsp1_video_suspend()
1148 ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe), in vsp1_video_suspend()
1151 dev_warn(vsp1->dev, "pipeline %u stop timeout\n", in vsp1_video_suspend()
1152 wpf->entity.index); in vsp1_video_suspend()
1162 for (i = 0; i < vsp1->info->wpf_count; ++i) { in vsp1_video_resume()
1163 struct vsp1_rwpf *wpf = vsp1->wpf[i]; in vsp1_video_resume()
1169 pipe = wpf->entity.pipe; in vsp1_video_resume()
1177 pipe->configured = false; in vsp1_video_resume()
1179 spin_lock_irqsave(&pipe->irqlock, flags); in vsp1_video_resume()
1182 spin_unlock_irqrestore(&pipe->irqlock, flags); in vsp1_video_resume()
1186 /* -----------------------------------------------------------------------------
1193 struct vsp1_video *video; in vsp1_video_create() local
1197 video = devm_kzalloc(vsp1->dev, sizeof(*video), GFP_KERNEL); in vsp1_video_create()
1198 if (!video) in vsp1_video_create()
1199 return ERR_PTR(-ENOMEM); in vsp1_video_create()
1201 rwpf->video = video; in vsp1_video_create()
1203 video->vsp1 = vsp1; in vsp1_video_create()
1204 video->rwpf = rwpf; in vsp1_video_create()
1206 if (rwpf->entity.type == VSP1_ENTITY_RPF) { in vsp1_video_create()
1208 video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; in vsp1_video_create()
1209 video->pad.flags = MEDIA_PAD_FL_SOURCE; in vsp1_video_create()
1210 video->video.vfl_dir = VFL_DIR_TX; in vsp1_video_create()
1211 video->video.device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | in vsp1_video_create()
1215 video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; in vsp1_video_create()
1216 video->pad.flags = MEDIA_PAD_FL_SINK; in vsp1_video_create()
1217 video->video.vfl_dir = VFL_DIR_RX; in vsp1_video_create()
1218 video->video.device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | in vsp1_video_create()
1222 mutex_init(&video->lock); in vsp1_video_create()
1223 spin_lock_init(&video->irqlock); in vsp1_video_create()
1224 INIT_LIST_HEAD(&video->irqqueue); in vsp1_video_create()
1227 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); in vsp1_video_create()
1232 rwpf->format.pixelformat = VSP1_VIDEO_DEF_FORMAT; in vsp1_video_create()
1233 rwpf->format.width = VSP1_VIDEO_DEF_WIDTH; in vsp1_video_create()
1234 rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT; in vsp1_video_create()
1235 __vsp1_video_try_format(video, &rwpf->format, &rwpf->fmtinfo); in vsp1_video_create()
1237 /* ... and the video node... */ in vsp1_video_create()
1238 video->video.v4l2_dev = &video->vsp1->v4l2_dev; in vsp1_video_create()
1239 video->video.entity.ops = &vsp1_video_media_ops; in vsp1_video_create()
1240 video->video.fops = &vsp1_video_fops; in vsp1_video_create()
1241 snprintf(video->video.name, sizeof(video->video.name), "%s %s", in vsp1_video_create()
1242 rwpf->entity.subdev.name, direction); in vsp1_video_create()
1243 video->video.vfl_type = VFL_TYPE_VIDEO; in vsp1_video_create()
1244 video->video.release = video_device_release_empty; in vsp1_video_create()
1245 video->video.ioctl_ops = &vsp1_video_ioctl_ops; in vsp1_video_create()
1247 video_set_drvdata(&video->video, video); in vsp1_video_create()
1249 video->queue.type = video->type; in vsp1_video_create()
1250 video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; in vsp1_video_create()
1251 video->queue.lock = &video->lock; in vsp1_video_create()
1252 video->queue.drv_priv = video; in vsp1_video_create()
1253 video->queue.buf_struct_size = sizeof(struct vsp1_vb2_buffer); in vsp1_video_create()
1254 video->queue.ops = &vsp1_video_queue_qops; in vsp1_video_create()
1255 video->queue.mem_ops = &vb2_dma_contig_memops; in vsp1_video_create()
1256 video->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in vsp1_video_create()
1257 video->queue.dev = video->vsp1->bus_master; in vsp1_video_create()
1258 ret = vb2_queue_init(&video->queue); in vsp1_video_create()
1260 dev_err(video->vsp1->dev, "failed to initialize vb2 queue\n"); in vsp1_video_create()
1264 /* ... and register the video device. */ in vsp1_video_create()
1265 video->video.queue = &video->queue; in vsp1_video_create()
1266 ret = video_register_device(&video->video, VFL_TYPE_VIDEO, -1); in vsp1_video_create()
1268 dev_err(video->vsp1->dev, "failed to register video device\n"); in vsp1_video_create()
1272 return video; in vsp1_video_create()
1275 vsp1_video_cleanup(video); in vsp1_video_create()
1279 void vsp1_video_cleanup(struct vsp1_video *video) in vsp1_video_cleanup() argument
1281 if (video_is_registered(&video->video)) in vsp1_video_cleanup()
1282 video_unregister_device(&video->video); in vsp1_video_cleanup()
1284 media_entity_cleanup(&video->video.entity); in vsp1_video_cleanup()