Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+53 −17
Original line number Original line Diff line number Diff line
@@ -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);
 *
 *
 * 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,
	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,
			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,
	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
+7 −0
Original line number Original line Diff line number Diff line
@@ -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;
};
};


+6 −3
Original line number Original line Diff line number Diff line
@@ -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__ */