Commit 7b4baddc authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] v4l: vsp1: Implement atomic update for the DRM driver

Add two API functions named vsp1_du_atomic_begin() and
vsp1_du_atomic_flush() to signal the start and end of an atomic update.
The vsp1_du_setup_rpf() function is renamed to vsp1_du_atomic_update()
for consistency.

With this new API, the driver will reprogram all modified inputs
atomically before restarting the video stream.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 3afb1939
...@@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
/** /**
* vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline * vsp1_du_atomic_begin - Prepare for an atomic update
* @dev: the VSP device
*/
void vsp1_du_atomic_begin(struct device *dev)
{
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
unsigned long flags;
spin_lock_irqsave(&pipe->irqlock, flags);
vsp1->drm->num_inputs = pipe->num_inputs;
vsp1->drm->update = false;
spin_unlock_irqrestore(&pipe->irqlock, flags);
}
EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
/**
* vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
* @dev: the VSP device * @dev: the VSP device
* @rpf_index: index of the RPF to setup (0-based) * @rpf_index: index of the RPF to setup (0-based)
* @pixelformat: V4L2 pixel format for the RPF memory input * @pixelformat: V4L2 pixel format for the RPF memory input
...@@ -288,7 +307,7 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif); ...@@ -288,7 +307,7 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
* *
* Return 0 on success or a negative error code on failure. * Return 0 on success or a negative error code on failure.
*/ */
int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
u32 pixelformat, unsigned int pitch, u32 pixelformat, unsigned int pitch,
dma_addr_t mem[2], const struct v4l2_rect *src, dma_addr_t mem[2], const struct v4l2_rect *src,
const struct v4l2_rect *dst) const struct v4l2_rect *dst)
...@@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, ...@@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
struct vsp1_rwpf_memory memory; struct vsp1_rwpf_memory memory;
struct vsp1_rwpf *rpf; struct vsp1_rwpf *rpf;
unsigned long flags; unsigned long flags;
bool start_stop = false;
int ret; int ret;
if (rpf_index >= vsp1->pdata.rpf_count) if (rpf_index >= vsp1->pdata.rpf_count)
...@@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, ...@@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
vsp1->bru->inputs[rpf_index].rpf = NULL; vsp1->bru->inputs[rpf_index].rpf = NULL;
pipe->inputs[rpf_index] = NULL; pipe->inputs[rpf_index] = NULL;
vsp1->drm->update = true; pipe->num_inputs--;
start_stop = --pipe->num_inputs == 0;
} }
spin_unlock_irqrestore(&pipe->irqlock, flags); spin_unlock_irqrestore(&pipe->irqlock, flags);
/* Stop the pipeline if we're the last user. */
if (start_stop)
vsp1_pipeline_stop(pipe);
return 0; return 0;
} }
...@@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index, ...@@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
if (!pipe->inputs[rpf->entity.index]) { if (!pipe->inputs[rpf->entity.index]) {
vsp1->bru->inputs[rpf_index].rpf = rpf; vsp1->bru->inputs[rpf_index].rpf = rpf;
pipe->inputs[rpf->entity.index] = rpf; pipe->inputs[rpf->entity.index] = rpf;
start_stop = pipe->num_inputs++ == 0; pipe->num_inputs++;
} }
/* Start the pipeline if it's currently stopped. */ spin_unlock_irqrestore(&pipe->irqlock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
/**
* vsp1_du_atomic_flush - Commit an atomic update
* @dev: the VSP device
*/
void vsp1_du_atomic_flush(struct device *dev)
{
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
unsigned long flags;
bool stop = false;
spin_lock_irqsave(&pipe->irqlock, flags);
vsp1->drm->update = true; vsp1->drm->update = true;
if (start_stop)
/* Start or stop the pipeline if needed. */
if (!vsp1->drm->num_inputs && pipe->num_inputs)
vsp1_drm_pipeline_run(pipe); vsp1_drm_pipeline_run(pipe);
else if (vsp1->drm->num_inputs && !pipe->num_inputs)
stop = true;
spin_unlock_irqrestore(&pipe->irqlock, flags); spin_unlock_irqrestore(&pipe->irqlock, flags);
return 0; if (stop)
vsp1_pipeline_stop(pipe);
} }
EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf); EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Initialization * Initialization
......
...@@ -15,8 +15,15 @@ ...@@ -15,8 +15,15 @@
#include "vsp1_pipe.h" #include "vsp1_pipe.h"
/**
* vsp1_drm - State for the API exposed to the DRM driver
* @pipe: the VSP1 pipeline used for display
* @num_inputs: number of active pipeline inputs at the beginning of an update
* @update: the pipeline configuration has been updated
*/
struct vsp1_drm { struct vsp1_drm {
struct vsp1_pipeline pipe; struct vsp1_pipeline pipe;
unsigned int num_inputs;
bool update; bool update;
}; };
......
...@@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev); ...@@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev);
int vsp1_du_setup_lif(struct device *dev, unsigned int width, int vsp1_du_setup_lif(struct device *dev, unsigned int width,
unsigned int height); unsigned int height);
int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat, int vsp1_du_atomic_begin(struct device *dev);
int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat,
unsigned int pitch, dma_addr_t mem[2], unsigned int pitch, dma_addr_t mem[2],
const struct v4l2_rect *src, const struct v4l2_rect *dst); const struct v4l2_rect *src,
const struct v4l2_rect *dst);
int vsp1_du_atomic_flush(struct device *dev);
#endif /* __MEDIA_VSP1_H__ */ #endif /* __MEDIA_VSP1_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment