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

Commit 07f1e3d0 authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: flush dynamic buffers held in driver



A dynamic buffer whose reference is pending
with f/w and queued back by client, will be
held in the driver. During flush, f/w will
release the reference, but driver should not
queue back the buffer to f/w.

Change-Id: If6fea08645a186691d49beaaf7a51a75f4b3121e
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent 79ca953a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -323,6 +323,8 @@ static inline void populate_buf_info(struct buffer_info *binfo,
	binfo->memory = b->memory;
	binfo->v4l2_index = b->index;
	binfo->dequeued = false;
	binfo->timestamp.tv_sec = b->timestamp.tv_sec;
	binfo->timestamp.tv_usec = b->timestamp.tv_usec;
	dprintk(VIDC_DBG, "%s: fd[%d] = %d b->index = %d",
			__func__, i, binfo->fd[0], b->index);
}
@@ -335,6 +337,8 @@ static inline void repopulate_v4l2_buffer(struct v4l2_buffer *b,
	b->length = binfo->num_planes;
	b->memory = binfo->memory;
	b->index = binfo->v4l2_index;
	b->timestamp.tv_sec = binfo->timestamp.tv_sec;
	b->timestamp.tv_usec = binfo->timestamp.tv_usec;
	for (i = 0; i < binfo->num_planes; ++i) {
		b->m.planes[i].reserved[0] = binfo->fd[i];
		b->m.planes[i].reserved[1] = binfo->buff_off[i];
+68 −0
Original line number Diff line number Diff line
@@ -543,10 +543,14 @@ static void handle_event_change(enum command_response cmd, void *data)
			break;
		}
		if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
			dprintk(VIDC_DBG,
				"V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
			inst->reconfig_height = event_notify->height;
			inst->reconfig_width = event_notify->width;
			inst->in_reconfig = true;
		} else {
			dprintk(VIDC_DBG,
				"V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
			inst->prop.height[CAPTURE_PORT] = event_notify->height;
			inst->prop.width[CAPTURE_PORT] = event_notify->width;
		}
@@ -2596,6 +2600,67 @@ static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
	msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
	return;
}

void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)
{
	struct buffer_info *binfo = NULL, *dummy = NULL;
	struct list_head *list = NULL;

	if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
		return;

	/*
	* dynamic buffer mode:- if flush is called during seek
	* driver should not queue any new buffer it has been holding.
	*
	* Each dynamic o/p buffer can have one of following ref_count:
	* ref_count : 0 - f/w has released reference and sent fbd back.
	*		  The buffer has been returned back to client.
	*
	* ref_count : 1 - f/w is holding reference. f/w may have released
	*                 fbd as read_only OR fbd is pending. f/w will
	*		  release reference before sending flush_done.
	*
	* ref_count : 2 - f/w is holding reference, f/w has released fbd as
	*                 read_only, which client has queued back to driver.
	*                 driver holds this buffer and will queue back
	*                 only when f/w releases the reference. During
	*		  flush_done, f/w will release the reference but driver
	*		  should not queue back the buffer to f/w.
	*		  Flush all buffers with ref_count 2.
	*/
	mutex_lock(&inst->lock);
	if (!list_empty(&inst->registered_bufs)) {
		struct v4l2_event buf_event = {0};
		u32 *ptr = NULL;
		list = &inst->registered_bufs;
		list_for_each_entry_safe(binfo, dummy, list, list) {
			if (binfo &&
			(binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
			(atomic_read(&binfo->ref_count) == 2)) {
				atomic_dec(&binfo->ref_count);
				buf_event.type =
				V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER;
				ptr = (u32 *)buf_event.u.data;
				ptr[0] = binfo->fd[0];
				ptr[1] = binfo->buff_off[0];
				ptr[2] = binfo->uvaddr[0];
				ptr[3] = (u32) binfo->timestamp.tv_sec;
				ptr[4] = (u32) binfo->timestamp.tv_usec;
				ptr[5] = binfo->v4l2_index;
				dprintk(VIDC_DBG,
					"released buffer held in driver before issuing flush: 0x%x fd[0]: %d\n",
					binfo->device_addr[0], binfo->fd[0]);
				/*send event to client*/
				v4l2_event_queue_fh(&inst->event_handler,
					&buf_event);
				wake_up(&inst->kernel_event_queue);
			}
		}
	}
	mutex_unlock(&inst->lock);
}

int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
{
	int rc =  0;
@@ -2671,6 +2736,9 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
				kfree(temp);
			}
		}

		msm_comm_flush_dynamic_buffers(inst);

		/*Do not send flush in case of session_error */
		if (!(inst->state == MSM_VIDC_CORE_INVALID &&
			  core->state != VIDC_CORE_INVALID))
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <linux/atomic.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/wait.h>
@@ -281,6 +282,7 @@ struct buffer_info {
	bool inactive;
	bool mapped[VIDEO_MAX_PLANES];
	int same_fd_ref[VIDEO_MAX_PLANES];
	struct timeval timestamp;
};

struct buffer_info *device_to_uvaddr(struct msm_vidc_inst *inst,
+2 −0
Original line number Diff line number Diff line
@@ -1776,6 +1776,8 @@ struct v4l2_streamparm {
#define V4L2_EVENT_MSM_VIDC_SYS_ERROR	(V4L2_EVENT_MSM_VIDC_START + 5)
#define V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE \
		(V4L2_EVENT_MSM_VIDC_START + 6)
#define V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER \
		(V4L2_EVENT_MSM_VIDC_START + 7)

/* Payload for V4L2_EVENT_VSYNC */
struct v4l2_event_vsync {