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

Commit f4223b7f authored by Praneeth Paladugu's avatar Praneeth Paladugu Committed by Gerrit - the friendly Code Review server
Browse files

msm: vidc: Add encoder input buffers dynamic



Video encoder clients can queue new input buffers anytime.
Hence video driver should handle them as dynamic buffers.

CRs-Fixed: 2023979
Change-Id: I13a6693122207984d290f227ab01186c2e8a4970
Signed-off-by: default avatarPraneeth Paladugu <ppaladug@codeaurora.org>
Signed-off-by: default avatarKarthikeyan Periasamy <kperiasa@codeaurora.org>
parent 4fed24d1
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -497,11 +497,12 @@ static inline enum hal_buffer get_hal_buffer_type(
		return -EINVAL;
}

static inline bool is_dynamic_output_buffer_mode(struct v4l2_buffer *b,
static inline bool is_dynamic_buffer_mode(struct v4l2_buffer *b,
				struct msm_vidc_inst *inst)
{
	return b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
		inst->buffer_mode_set[CAPTURE_PORT] == HAL_BUFFER_MODE_DYNAMIC;
	enum vidc_ports port = b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
		OUTPUT_PORT : CAPTURE_PORT;
	return inst->buffer_mode_set[port] == HAL_BUFFER_MODE_DYNAMIC;
}


@@ -558,7 +559,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
		}
		mutex_lock(&inst->registeredbufs.lock);
		temp = get_registered_buf(inst, b, i, &plane);
		if (temp && !is_dynamic_output_buffer_mode(b, inst)) {
		if (temp && !is_dynamic_buffer_mode(b, inst)) {
			dprintk(VIDC_DBG,
				"This memory region has already been prepared\n");
			rc = 0;
@@ -566,7 +567,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
			goto exit;
		}

		if (temp && is_dynamic_output_buffer_mode(b, inst) && !i) {
		if (temp && is_dynamic_buffer_mode(b, inst) && !i) {
			/*
			 * Buffer is already present in registered list
			 * increment ref_count, populate new values of v4l2
@@ -599,7 +600,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
		if (rc == 1) {
			rc = 0;
			goto exit;
		} else if (rc == 2) {
		} else if (rc >= 2) {
			rc = -EEXIST;
			goto exit;
		}
@@ -629,7 +630,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
		}

		/* We maintain one ref count for all planes*/
		if (!i && is_dynamic_output_buffer_mode(b, inst)) {
		if (!i && is_dynamic_buffer_mode(b, inst)) {
			rc = buf_ref_get(inst, binfo);
			if (rc < 0)
				goto exit;
@@ -874,7 +875,7 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
	rc = map_and_register_buf(inst, b);
	if (rc == -EEXIST) {
		if (atomic_read(&inst->in_flush) &&
			is_dynamic_output_buffer_mode(b, inst)) {
			is_dynamic_buffer_mode(b, inst)) {
			dprintk(VIDC_ERR,
				"Flush in progress, do not hold any buffers in driver\n");
			msm_comm_flush_dynamic_buffers(inst);
@@ -998,7 +999,7 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
		return rc;


	if (is_dynamic_output_buffer_mode(b, inst)) {
	if (is_dynamic_buffer_mode(b, inst)) {
		buffer_info->dequeued = true;

		dprintk(VIDC_DBG, "[DEQUEUED]: fd[0] = %d\n",
+59 −58
Original line number Diff line number Diff line
@@ -2163,6 +2163,43 @@ static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq,
	return vb;
}

static void handle_dynamic_buffer(struct msm_vidc_inst *inst,
		ion_phys_addr_t device_addr, u32 flags)
{
	struct buffer_info *binfo = NULL, *temp = NULL;

	/*
	 * Update reference count and release OR queue back the buffer,
	 * only when firmware is not holding a reference.
	 */
	binfo = device_to_uvaddr(&inst->registeredbufs, device_addr);
	if (!binfo) {
		dprintk(VIDC_ERR,
			"%s buffer not found in registered list\n",
			__func__);
		return;
	}
	if (flags & HAL_BUFFERFLAG_READONLY) {
		dprintk(VIDC_DBG,
			"FBD fd[0] = %d -> Reference with f/w, addr: %pa\n",
			binfo->fd[0], &device_addr);
	} else {
		dprintk(VIDC_DBG,
			"FBD fd[0] = %d -> FBD_ref_released, addr: %pa\n",
			binfo->fd[0], &device_addr);

		mutex_lock(&inst->registeredbufs.lock);
		list_for_each_entry(temp, &inst->registeredbufs.list,
				list) {
			if (temp == binfo) {
				buf_ref_put(inst, binfo);
				break;
			}
		}
		mutex_unlock(&inst->registeredbufs.lock);
	}
}

static void handle_ebd(enum hal_command_response cmd, void *data)
{
	struct msm_vidc_cb_data_done *response = data;
@@ -2182,6 +2219,9 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
		dprintk(VIDC_WARN, "Got a response for an inactive session\n");
		return;
	}
	if (inst->buffer_mode_set[OUTPUT_PORT] == HAL_BUFFER_MODE_DYNAMIC)
		handle_dynamic_buffer(inst,
			response->input_done.packet_buffer, 0);

	vb = get_vb_from_device_addr(&inst->bufq[OUTPUT_PORT],
			response->input_done.packet_buffer);
@@ -2239,11 +2279,7 @@ int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo)

	atomic_inc(&binfo->ref_count);
	cnt = atomic_read(&binfo->ref_count);
	if (cnt > 2) {
		dprintk(VIDC_DBG, "%s: invalid ref_cnt: %d\n", __func__, cnt);
		cnt = -EINVAL;
	}
	if (cnt == 2)
	if (cnt >= 2)
		inst->buffers_held_in_driver++;

	dprintk(VIDC_DBG, "REF_GET[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
@@ -2266,7 +2302,7 @@ int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo)
	dprintk(VIDC_DBG, "REF_PUT[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
	if (!cnt)
		release_buf = true;
	else if (cnt == 1)
	else if (cnt >= 1)
		qbuf_again = true;
	else {
		dprintk(VIDC_DBG, "%s: invalid ref_cnt: %d\n", __func__, cnt);
@@ -2297,45 +2333,6 @@ int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo)
	return cnt;
}

static void handle_dynamic_buffer(struct msm_vidc_inst *inst,
		ion_phys_addr_t device_addr, u32 flags)
{
	struct buffer_info *binfo = NULL, *temp = NULL;

	/*
	 * Update reference count and release OR queue back the buffer,
	 * only when firmware is not holding a reference.
	 */
	if (inst->buffer_mode_set[CAPTURE_PORT] == HAL_BUFFER_MODE_DYNAMIC) {
		binfo = device_to_uvaddr(&inst->registeredbufs, device_addr);
		if (!binfo) {
			dprintk(VIDC_ERR,
				"%s buffer not found in registered list\n",
				__func__);
			return;
		}
		if (flags & HAL_BUFFERFLAG_READONLY) {
			dprintk(VIDC_DBG,
				"FBD fd[0] = %d -> Reference with f/w, addr: %pa\n",
				binfo->fd[0], &device_addr);
		} else {
			dprintk(VIDC_DBG,
				"FBD fd[0] = %d -> FBD_ref_released, addr: %pa\n",
				binfo->fd[0], &device_addr);

			mutex_lock(&inst->registeredbufs.lock);
			list_for_each_entry(temp, &inst->registeredbufs.list,
							list) {
				if (temp == binfo) {
					buf_ref_put(inst, binfo);
					break;
				}
			}
			mutex_unlock(&inst->registeredbufs.lock);
		}
	}
}

static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
		ion_phys_addr_t dev_addr)
{
@@ -2459,6 +2456,8 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
			vb->planes[extra_idx].data_offset = 0;
		}

		if (inst->buffer_mode_set[CAPTURE_PORT] ==
			HAL_BUFFER_MODE_DYNAMIC)
		handle_dynamic_buffer(inst, fill_buf_done->packet_buffer1,
					fill_buf_done->flags1);
		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
@@ -4854,20 +4853,22 @@ void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)
	 * 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 : 0   - f/w has released reference and sent dynamic
	 *                   buffer 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.
	 *                   dynamic buffer as read_only OR dynamic buffer 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.
	 * ref_count : >=2 - f/w is holding reference, f/w has released dynamic
	 *                   buffer 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->registeredbufs.lock);
	if (!list_empty(&inst->registeredbufs.list)) {
@@ -4876,7 +4877,7 @@ void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)

		list_for_each_entry(binfo, &inst->registeredbufs.list, list) {
			if (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
				atomic_read(&binfo->ref_count) == 2) {
				atomic_read(&binfo->ref_count) >= 2) {

				atomic_dec(&binfo->ref_count);
				buf_event.type =
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static struct debug_buffer dbg_buf;
})

#define DYNAMIC_BUF_OWNER(__binfo) ({ \
	atomic_read(&__binfo->ref_count) == 2 ? "video driver" : "firmware";\
	atomic_read(&__binfo->ref_count) >= 2 ? "video driver" : "firmware";\
})

static int core_info_open(struct inode *inode, struct file *file)