[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: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
parent
3afb193991
commit
7b4baddca6
|
@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
|
|||
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
|
||||
* @rpf_index: index of the RPF to setup (0-based)
|
||||
* @pixelformat: V4L2 pixel format for the RPF memory input
|
||||
|
@ -288,10 +307,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
|
|||
*
|
||||
* Return 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
|
||||
u32 pixelformat, unsigned int pitch,
|
||||
dma_addr_t mem[2], const struct v4l2_rect *src,
|
||||
const struct v4l2_rect *dst)
|
||||
int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
|
||||
u32 pixelformat, unsigned int pitch,
|
||||
dma_addr_t mem[2], const struct v4l2_rect *src,
|
||||
const struct v4l2_rect *dst)
|
||||
{
|
||||
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
|
||||
struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
|
||||
|
@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
|
|||
struct vsp1_rwpf_memory memory;
|
||||
struct vsp1_rwpf *rpf;
|
||||
unsigned long flags;
|
||||
bool start_stop = false;
|
||||
int ret;
|
||||
|
||||
if (rpf_index >= vsp1->pdata.rpf_count)
|
||||
|
@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
|
|||
vsp1->bru->inputs[rpf_index].rpf = NULL;
|
||||
pipe->inputs[rpf_index] = NULL;
|
||||
|
||||
vsp1->drm->update = true;
|
||||
start_stop = --pipe->num_inputs == 0;
|
||||
pipe->num_inputs--;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pipe->irqlock, flags);
|
||||
|
||||
/* Stop the pipeline if we're the last user. */
|
||||
if (start_stop)
|
||||
vsp1_pipeline_stop(pipe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
|
|||
if (!pipe->inputs[rpf->entity.index]) {
|
||||
vsp1->bru->inputs[rpf_index].rpf = rpf;
|
||||
pipe->inputs[rpf->entity.index] = rpf;
|
||||
start_stop = pipe->num_inputs++ == 0;
|
||||
pipe->num_inputs++;
|
||||
}
|
||||
|
||||
/* Start the pipeline if it's currently stopped. */
|
||||
vsp1->drm->update = true;
|
||||
if (start_stop)
|
||||
vsp1_drm_pipeline_run(pipe);
|
||||
|
||||
spin_unlock_irqrestore(&pipe->irqlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf);
|
||||
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;
|
||||
|
||||
/* Start or stop the pipeline if needed. */
|
||||
if (!vsp1->drm->num_inputs && pipe->num_inputs)
|
||||
vsp1_drm_pipeline_run(pipe);
|
||||
else if (vsp1->drm->num_inputs && !pipe->num_inputs)
|
||||
stop = true;
|
||||
|
||||
spin_unlock_irqrestore(&pipe->irqlock, flags);
|
||||
|
||||
if (stop)
|
||||
vsp1_pipeline_stop(pipe);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Initialization
|
||||
|
|
|
@ -15,8 +15,15 @@
|
|||
|
||||
#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_pipeline pipe;
|
||||
unsigned int num_inputs;
|
||||
bool update;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev);
|
|||
int vsp1_du_setup_lif(struct device *dev, unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat,
|
||||
unsigned int pitch, dma_addr_t mem[2],
|
||||
const struct v4l2_rect *src, const struct v4l2_rect *dst);
|
||||
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],
|
||||
const struct v4l2_rect *src,
|
||||
const struct v4l2_rect *dst);
|
||||
int vsp1_du_atomic_flush(struct device *dev);
|
||||
|
||||
#endif /* __MEDIA_VSP1_H__ */
|
||||
|
|
Loading…
Reference in New Issue