Commit 89f9829c authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

media: atomisp: Also track buffers in a list when submitted to the ISP



Instead of using an integer to keep count of how many buffers have
been handed over to the ISP (buffers_in_css) move buffers handed
over to the ISP to a new buffers_in_css list_head so that we can
easily loop over them.

This removes the need for atomisp_flush_video_pipe() to loop over
all buffers and then (ab)use the state to figure out if they
were handed over to the ISP.

Since the buffers are now always on a list when owned by the driver
this also allows the buffer_done path on flush vs normal completion
to be unified (both now need a list_del()) and this common code can
now be factored out into a new atomisp_buffer_done() helper.

This is a preparation patch for moving the driver over to
the videobuf2 framework.

Reviewed-by: default avatarAndy Shevchenko <andy@kernel.org>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent b895be29
Loading
Loading
Loading
Loading
+50 −41
Original line number Diff line number Diff line
@@ -634,10 +634,6 @@ void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd)
		memset(asd->metadata_bufs_in_css[i], 0,
		       sizeof(asd->metadata_bufs_in_css[i]));
	asd->dis_bufs_in_css = 0;
	asd->video_out_capture.buffers_in_css = 0;
	asd->video_out_vf.buffers_in_css = 0;
	asd->video_out_preview.buffers_in_css = 0;
	asd->video_out_video_capture.buffers_in_css = 0;
}

/* 0x100000 is the start of dmem inside SP */
@@ -683,40 +679,65 @@ static struct videobuf_buffer *atomisp_css_frame_to_vbuf(
	return NULL;
}

static void atomisp_flush_video_pipe(struct atomisp_sub_device *asd,
				     struct atomisp_video_pipe *pipe)
int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe)
{
	unsigned long irqflags;
	int i;
	struct list_head *pos;
	int buffers_in_css = 0;

	if (!pipe->users)
		return;
	spin_lock_irqsave(&pipe->irq_lock, irqflags);

	list_for_each(pos, &pipe->buffers_in_css)
		buffers_in_css++;

	spin_unlock_irqrestore(&pipe->irq_lock, irqflags);

	return buffers_in_css;
}

void atomisp_buffer_done(struct atomisp_video_pipe *pipe, struct videobuf_buffer *vb,
			 int state)
{
	lockdep_assert_held(&pipe->irq_lock);

	vb->ts = ktime_get_ns();
	vb->field_count = atomic_read(&pipe->asd->sequence) << 1;
	vb->state = state;
	list_del(&vb->queue);
	wake_up(&vb->done);
}

void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, bool warn_on_css_frames)
{
	struct videobuf_buffer *_vb, *vb;
	unsigned long irqflags;

	for (i = 0; pipe->capq.bufs[i]; i++) {
	spin_lock_irqsave(&pipe->irq_lock, irqflags);
		if (pipe->capq.bufs[i]->state == VIDEOBUF_ACTIVE ||
		    pipe->capq.bufs[i]->state == VIDEOBUF_QUEUED) {
			pipe->capq.bufs[i]->ts = ktime_get_ns();
			pipe->capq.bufs[i]->field_count =
			    atomic_read(&asd->sequence) << 1;
			dev_dbg(asd->isp->dev, "release buffers on device %s\n",
				pipe->vdev.name);
			if (pipe->capq.bufs[i]->state == VIDEOBUF_QUEUED)
				list_del_init(&pipe->capq.bufs[i]->queue);
			pipe->capq.bufs[i]->state = VIDEOBUF_ERROR;
			wake_up(&pipe->capq.bufs[i]->done);

	list_for_each_entry_safe(vb, _vb, &pipe->buffers_in_css, queue) {
		if (warn_on_css_frames)
			dev_warn(pipe->isp->dev, "Warning: CSS frames queued on flush\n");
		atomisp_buffer_done(pipe, vb, VIDEOBUF_ERROR);
	}
		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);

	list_for_each_entry_safe(vb, _vb, &pipe->activeq, queue)
		atomisp_buffer_done(pipe, vb, VIDEOBUF_ERROR);

	list_for_each_entry_safe(vb, _vb, &pipe->buffers_waiting_for_param, queue) {
		pipe->frame_request_config_id[vb->i] = 0;
		atomisp_buffer_done(pipe, vb, VIDEOBUF_ERROR);
	}

	spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
}

/* Returns queued buffers back to video-core */
void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd)
{
	atomisp_flush_video_pipe(asd, &asd->video_out_capture);
	atomisp_flush_video_pipe(asd, &asd->video_out_vf);
	atomisp_flush_video_pipe(asd, &asd->video_out_preview);
	atomisp_flush_video_pipe(asd, &asd->video_out_video_capture);
	atomisp_flush_video_pipe(&asd->video_out_capture, false);
	atomisp_flush_video_pipe(&asd->video_out_vf, false);
	atomisp_flush_video_pipe(&asd->video_out_preview, false);
	atomisp_flush_video_pipe(&asd->video_out_video_capture, false);
}

/* clean out the parameters that did not apply */
@@ -974,7 +995,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
		break;
	case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
	case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
		pipe->buffers_in_css--;
		frame = buffer.css_buffer.data.frame;
		if (!frame) {
			WARN_ON(1);
@@ -1026,7 +1046,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
		break;
	case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
	case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
		pipe->buffers_in_css--;
		frame = buffer.css_buffer.data.frame;
		if (!frame) {
			WARN_ON(1);
@@ -1179,19 +1198,9 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
		break;
	}
	if (vb) {
		vb->ts = ktime_get_ns();
		vb->field_count = atomic_read(&asd->sequence) << 1;
		/*mark videobuffer done for dequeue*/
		spin_lock_irqsave(&pipe->irq_lock, irqflags);
		vb->state = !error ? VIDEOBUF_DONE : VIDEOBUF_ERROR;
		atomisp_buffer_done(pipe, vb, error ? VIDEOBUF_ERROR : VIDEOBUF_DONE);
		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);

		/*
		 * Frame capture done, wake up any process block on
		 * current active buffer
		 * possibly hold by videobuf_dqbuf()
		 */
		wake_up(&vb->done);
	}

	/*
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,10 @@ void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr,
struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd);
struct atomisp_video_pipe *atomisp_to_video_pipe(struct video_device *dev);
int atomisp_reset(struct atomisp_device *isp);
int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe);
void atomisp_buffer_done(struct atomisp_video_pipe *pipe, struct videobuf_buffer *buf,
			 int state);
void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, bool warn_on_css_frames);
void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd);
void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd);

+13 −11
Original line number Diff line number Diff line
@@ -217,7 +217,9 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
	struct ia_css_dvs_grid_info *dvs_grid =
	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
	unsigned long irqflags;
	int err = 0;
	int space, err = 0;

	lockdep_assert_held(&asd->isp->mutex);

	if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM))
		return -EINVAL;
@@ -225,20 +227,21 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
	if (pipe->stopping)
		return -EINVAL;

	while (pipe->buffers_in_css < ATOMISP_CSS_Q_DEPTH) {
	space = ATOMISP_CSS_Q_DEPTH - atomisp_buffers_in_css(pipe);
	while (space--) {
		struct videobuf_buffer *vb;

		spin_lock_irqsave(&pipe->irq_lock, irqflags);
		if (list_empty(&pipe->activeq)) {
			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
			return -EINVAL;
		}
		vb = list_entry(pipe->activeq.next,
				struct videobuf_buffer, queue);
		list_del_init(&vb->queue);
		vb = list_first_entry_or_null(&pipe->activeq, struct videobuf_buffer, queue);
		if (vb) {
			list_move_tail(&vb->queue, &pipe->buffers_in_css);
			vb->state = VIDEOBUF_ACTIVE;
		}
		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);

		if (!vb)
			return -EINVAL;

		/*
		 * If there is a per_frame setting to apply on the buffer,
		 * do it before buffer en-queueing.
@@ -291,14 +294,13 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
						    css_buf_type, css_pipe_id);
		if (err) {
			spin_lock_irqsave(&pipe->irq_lock, irqflags);
			list_add_tail(&vb->queue, &pipe->activeq);
			list_move_tail(&vb->queue, &pipe->activeq);
			vb->state = VIDEOBUF_QUEUED;
			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
			dev_err(asd->isp->dev, "%s, css q fails: %d\n",
				__func__, err);
			return -EINVAL;
		}
		pipe->buffers_in_css++;

		/* enqueue 3A/DIS/metadata buffers */
		if (asd->params.curr_grid_info.s3a_grid.enable &&
+1 −1
Original line number Diff line number Diff line
@@ -1762,7 +1762,7 @@ int atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
	mutex_unlock(&isp->mutex);
	/* wait max 1 second */
	ret = wait_event_interruptible_timeout(pipe->capq.wait,
					       pipe->buffers_in_css == 0, HZ);
					       atomisp_buffers_in_css(pipe) == 0, HZ);
	mutex_lock(&isp->mutex);
	pipe->stopping = false;
	if (ret <= 0)
+1 −0
Original line number Diff line number Diff line
@@ -1064,6 +1064,7 @@ static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
	pipe->asd = asd;
	pipe->isp = asd->isp;
	spin_lock_init(&pipe->irq_lock);
	INIT_LIST_HEAD(&pipe->buffers_in_css);
	INIT_LIST_HEAD(&pipe->activeq);
	INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
	INIT_LIST_HEAD(&pipe->per_frame_params);
Loading