diff options
Diffstat (limited to 'drivers/media/platform/vsp1/vsp1_video.c')
| -rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 714c53ef6c1..8a1253e51f0 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1,7 +1,7 @@ /* * vsp1_video.c -- R-Car VSP1 Video Node * - * Copyright (C) 2013 Renesas Corporation + * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) * @@ -28,6 +28,7 @@ #include <media/videobuf2-dma-contig.h> #include "vsp1.h" +#include "vsp1_bru.h" #include "vsp1_entity.h" #include "vsp1_rwpf.h" #include "vsp1_video.h" @@ -280,6 +281,9 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, struct media_pad *pad; bool uds_found = false; + input->location.left = 0; + input->location.top = 0; + pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); while (1) { @@ -292,6 +296,17 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); + /* A BRU is present in the pipeline, store the compose rectangle + * location in the input RPF for use when configuring the RPF. + */ + if (entity->type == VSP1_ENTITY_BRU) { + struct vsp1_bru *bru = to_bru(&entity->subdev); + struct v4l2_rect *rect = &bru->compose[pad->index]; + + input->location.left = rect->left; + input->location.top = rect->top; + } + /* We've reached the WPF, we're done. */ if (entity->type == VSP1_ENTITY_WPF) break; @@ -363,6 +378,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, rwpf->video.pipe_index = 0; } else if (e->type == VSP1_ENTITY_LIF) { pipe->lif = e; + } else if (e->type == VSP1_ENTITY_BRU) { + pipe->bru = e; } } @@ -392,6 +409,7 @@ error: pipe->num_video = 0; pipe->num_inputs = 0; pipe->output = NULL; + pipe->bru = NULL; pipe->lif = NULL; return ret; } @@ -430,6 +448,7 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) pipe->num_video = 0; pipe->num_inputs = 0; pipe->output = NULL; + pipe->bru = NULL; pipe->lif = NULL; } @@ -461,7 +480,7 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) list_for_each_entry(entity, &pipe->entities, list_pipe) { if (entity->route) - vsp1_write(entity->vsp1, entity->route, + vsp1_write(entity->vsp1, entity->route->reg, VI6_DPR_NODE_UNUSED); v4l2_subdev_call(&entity->subdev, video, s_stream, 0); @@ -488,11 +507,17 @@ static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) * This function completes the current buffer by filling its sequence number, * time stamp and payload size, and hands it back to the videobuf core. * + * When operating in DU output mode (deep pipeline to the DU through the LIF), + * the VSP1 needs to constantly supply frames to the display. In that case, if + * no other buffer is queued, reuse the one that has just been processed instead + * of handing it back to the videobuf core. + * * Return the next queued buffer or NULL if the queue is empty. */ static struct vsp1_video_buffer * vsp1_video_complete_buffer(struct vsp1_video *video) { + struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); struct vsp1_video_buffer *next = NULL; struct vsp1_video_buffer *done; unsigned long flags; @@ -507,6 +532,13 @@ vsp1_video_complete_buffer(struct vsp1_video *video) done = list_first_entry(&video->irqqueue, struct vsp1_video_buffer, queue); + + /* In DU output mode reuse the buffer if the list is singular. */ + if (pipe->lif && list_is_singular(&video->irqqueue)) { + spin_unlock_irqrestore(&video->irqlock, flags); + return done; + } + list_del(&done->queue); if (!list_empty(&video->irqqueue)) @@ -667,11 +699,12 @@ static void vsp1_entity_route_setup(struct vsp1_entity *source) { struct vsp1_entity *sink; - if (source->route == 0) + if (source->route->reg == 0) return; sink = container_of(source->sink, struct vsp1_entity, subdev.entity); - vsp1_write(source->vsp1, source->route, sink->id); + vsp1_write(source->vsp1, source->route->reg, + sink->route->inputs[source->sink_pad]); } static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) @@ -707,7 +740,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) return 0; } -static int vsp1_video_stop_streaming(struct vb2_queue *vq) +static void vsp1_video_stop_streaming(struct vb2_queue *vq) { struct vsp1_video *video = vb2_get_drv_priv(vq); struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); @@ -730,8 +763,6 @@ static int vsp1_video_stop_streaming(struct vb2_queue *vq) spin_lock_irqsave(&video->irqlock, flags); INIT_LIST_HEAD(&video->irqqueue); spin_unlock_irqrestore(&video->irqlock, flags); - - return 0; } static struct vb2_ops vsp1_video_queue_qops = { @@ -1026,8 +1057,10 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) /* ... and the buffers queue... */ video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev); - if (IS_ERR(video->alloc_ctx)) + if (IS_ERR(video->alloc_ctx)) { + ret = PTR_ERR(video->alloc_ctx); goto error; + } video->queue.type = video->type; video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; @@ -1036,7 +1069,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) video->queue.buf_struct_size = sizeof(struct vsp1_video_buffer); video->queue.ops = &vsp1_video_queue_qops; video->queue.mem_ops = &vb2_dma_contig_memops; - video->queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + video->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ret = vb2_queue_init(&video->queue); if (ret < 0) { dev_err(video->vsp1->dev, "failed to initialize vb2 queue\n"); |
