v4l: vsp1: Repair suspend resume operations for video pipelines
When a suspend/resume action is taken, the pipeline is reset and never
reconfigured.
To correct this, we establish a new flag pipe->configured and utilise
this to establish when we write a full configuration set to the current
display list.
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index aa237b4..d596cde 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -413,6 +413,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index)
{
+ struct vsp1_rwpf *wpf = vsp1->wpf[index];
unsigned int timeout;
u32 status;
@@ -429,6 +430,9 @@ int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index)
usleep_range(1000, 2000);
}
+ if (wpf->pipe)
+ wpf->pipe->configured = false;
+
if (!timeout) {
dev_err(vsp1->dev, "failed to reset wpf.%u\n", index);
return -ETIMEDOUT;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 280ba08..c568db1 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -216,6 +216,7 @@ void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
INIT_LIST_HEAD(&pipe->entities);
pipe->state = VSP1_PIPELINE_STOPPED;
+ pipe->configured = false;
}
/* Must be called with the pipe irqlock held. */
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index bc419ef..1b1da7e 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -64,6 +64,7 @@ enum vsp1_pipeline_state {
* @pipe: the media pipeline
* @irqlock: protects the pipeline state
* @state: current state
+ * @configured: true if the pipeline has been set up for video streaming
* @wq: wait queue to wait for state change completion
* @frame_end: frame end interrupt handler
* @lock: protects the pipeline use count and stream count
@@ -89,6 +90,7 @@ struct vsp1_pipeline {
spinlock_t irqlock;
enum vsp1_pipeline_state state;
+ bool configured;
wait_queue_head_t wq;
void (*frame_end)(struct vsp1_pipeline *pipe);
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 970be4d..84d3538 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -359,18 +359,14 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
pipe->buffers_ready |= 1 << video->pipe_index;
}
-static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
+static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe,
+ struct vsp1_dl_list *dl)
{
struct vsp1_entity *entity;
/* Determine this pipelines sizes for image partitioning support. */
vsp1_video_pipeline_setup_partitions(pipe);
- /* Prepare the display list. */
- pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
- if (!pipe->dl)
- return -ENOMEM;
-
if (pipe->uds) {
struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
@@ -390,13 +386,15 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
}
list_for_each_entry(entity, &pipe->entities, list_pipe) {
- vsp1_entity_route_setup(entity, pipe->dl);
+ vsp1_entity_route_setup(entity, dl);
if (entity->ops->configure)
- entity->ops->configure(entity, pipe, pipe->dl,
+ entity->ops->configure(entity, pipe, dl,
VSP1_ENTITY_PARAMS_INIT);
}
+ pipe->configured = true;
+
return 0;
}
@@ -419,10 +417,17 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
{
struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
struct vsp1_entity *entity;
+ struct vsp1_dl_list *dl;
unsigned int current_partition = 0;
- if (!pipe->dl)
- pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
+ dl = vsp1_dl_list_get(pipe->output->dlm);
+ if (!dl) {
+ dev_err(vsp1->dev, "Failed to obtain a dl list\n");
+ return;
+ }
+
+ if (!pipe->configured)
+ vsp1_video_setup_pipeline(pipe, dl);
/*
* Start with the runtime parameters as the configure operation can
@@ -431,44 +436,42 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
*/
list_for_each_entry(entity, &pipe->entities, list_pipe) {
if (entity->ops->configure)
- entity->ops->configure(entity, pipe, pipe->dl,
+ entity->ops->configure(entity, pipe, dl,
VSP1_ENTITY_PARAMS_RUNTIME);
}
/* Run the first partition */
- vsp1_video_pipeline_run_partition(pipe, pipe->dl, current_partition);
+ vsp1_video_pipeline_run_partition(pipe, dl, current_partition);
/* Process consecutive partitions as necessary */
for (current_partition = 1;
current_partition < pipe->partitions;
current_partition++) {
- struct vsp1_dl_list *dl;
+ struct vsp1_dl_list *child;
/*
* Partition configuration operations will utilise
* the pipe->current_partition variable to determine
* the work they should complete.
*/
- dl = vsp1_dl_list_get(pipe->output->dlm);
+ child = vsp1_dl_list_get(pipe->output->dlm);
/*
* An incomplete chain will still function, but output only
* the partitions that had a dl available. The frame end
* interrupt will be marked on the last dl in the chain.
*/
- if (!dl) {
+ if (!child) {
dev_err(vsp1->dev, "Failed to obtain a dl list. Frame will be incomplete\n");
break;
}
- vsp1_video_pipeline_run_partition(pipe, dl, current_partition);
- vsp1_dl_list_add_chain(pipe->dl, dl);
+ vsp1_video_pipeline_run_partition(pipe, child, current_partition);
+ vsp1_dl_list_add_chain(dl, child);
}
/* Complete, and commit the head display list. */
- vsp1_dl_list_commit(pipe->dl);
- pipe->dl = NULL;
-
+ vsp1_dl_list_commit(dl);
vsp1_pipeline_run(pipe);
}
@@ -829,18 +832,10 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
struct vsp1_pipeline *pipe = video->rwpf->pipe;
bool start_pipeline = false;
unsigned long flags;
- int ret;
mutex_lock(&pipe->lock);
- if (pipe->stream_count == pipe->num_inputs) {
- ret = vsp1_video_setup_pipeline(pipe);
- if (ret < 0) {
- mutex_unlock(&pipe->lock);
- return ret;
- }
-
+ if (pipe->stream_count == pipe->num_inputs)
start_pipeline = true;
- }
pipe->stream_count++;
mutex_unlock(&pipe->lock);
@@ -885,9 +880,6 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
ret = vsp1_pipeline_stop(pipe);
if (ret == -ETIMEDOUT)
dev_err(video->vsp1->dev, "pipeline stop timeout\n");
-
- vsp1_dl_list_put(pipe->dl);
- pipe->dl = NULL;
}
mutex_unlock(&pipe->lock);