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

Commit 09a93f80 authored by Govindaraj Rajagopal's avatar Govindaraj Rajagopal
Browse files

msm: vidc: add support for input_tag, input_tag2 and sub-frame info



1. Client needs input etb to output fbd association. Introducing
   input_tag and input_tag2 fields for this. Client will send
   input_tag via etb reserved fields and client will get back
   those as part of fbd reserved fields.
2. Convey sub-frame information to client from firmware.

CRs-Fixed: 2494945

Change-Id: Ic64131c7f8f3e3035cd6ff3997fe483171d71fc4
Signed-off-by: default avatarGovindaraj Rajagopal <grajagop@codeaurora.org>
parent 0f6ff621
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -632,12 +632,10 @@ int create_pkt_cmd_session_etb_decoder(
	pkt->time_stamp_hi = upper_32_bits(input_frame->timestamp);
	pkt->time_stamp_lo = lower_32_bits(input_frame->timestamp);
	pkt->flags = input_frame->flags;
	pkt->mark_target = input_frame->mark_target;
	pkt->mark_data = input_frame->mark_data;
	pkt->offset = input_frame->offset;
	pkt->alloc_len = input_frame->alloc_len;
	pkt->filled_len = input_frame->filled_len;
	pkt->input_tag = input_frame->clnt_data;
	pkt->input_tag = input_frame->input_tag;
	pkt->packet_buffer = (u32)input_frame->device_addr;

	trace_msm_v4l2_vidc_buffer_event_start("ETB",
@@ -667,12 +665,10 @@ int create_pkt_cmd_session_etb_encoder(
	pkt->time_stamp_hi = upper_32_bits(input_frame->timestamp);
	pkt->time_stamp_lo = lower_32_bits(input_frame->timestamp);
	pkt->flags = input_frame->flags;
	pkt->mark_target = input_frame->mark_target;
	pkt->mark_data = input_frame->mark_data;
	pkt->offset = input_frame->offset;
	pkt->alloc_len = input_frame->alloc_len;
	pkt->filled_len = input_frame->filled_len;
	pkt->input_tag = input_frame->clnt_data;
	pkt->input_tag = input_frame->input_tag;
	pkt->packet_buffer = (u32)input_frame->device_addr;
	pkt->extra_data_buffer = (u32)input_frame->extradata_addr;

+4 −8
Original line number Diff line number Diff line
@@ -780,7 +780,7 @@ static int hfi_process_session_etb_done(u32 device_id,
	data_done.session_id = (void *)(uintptr_t)pkt->session_id;
	data_done.status = hfi_map_err_status(pkt->error_type);
	data_done.size = sizeof(struct msm_vidc_cb_data_done);
	data_done.clnt_data = pkt->input_tag;
	data_done.input_done.input_tag = pkt->input_tag;
	data_done.input_done.recon_stats.buffer_index =
		pkt->ubwc_cr_stats.frame_index;
	memcpy(&data_done.input_done.recon_stats.ubwc_stats_info,
@@ -857,13 +857,11 @@ static int hfi_process_session_ftb_done(
		data_done.session_id = (void *)(uintptr_t)pkt->session_id;
		data_done.status = hfi_map_err_status(pkt->error_type);
		data_done.size = sizeof(struct msm_vidc_cb_data_done);
		data_done.clnt_data = 0;

		data_done.output_done.input_tag = pkt->input_tag;
		data_done.output_done.timestamp_hi = pkt->time_stamp_hi;
		data_done.output_done.timestamp_lo = pkt->time_stamp_lo;
		data_done.output_done.flags1 = pkt->flags;
		data_done.output_done.mark_target = pkt->mark_target;
		data_done.output_done.mark_data = pkt->mark_data;
		data_done.output_done.stats = pkt->stats;
		data_done.output_done.offset1 = pkt->offset;
		data_done.output_done.alloc_len1 = pkt->alloc_len;
@@ -892,15 +890,12 @@ static int hfi_process_session_ftb_done(
		data_done.session_id = (void *)(uintptr_t)pkt->session_id;
		data_done.status = hfi_map_err_status(pkt->error_type);
		data_done.size = sizeof(struct msm_vidc_cb_data_done);
		data_done.clnt_data = 0;

		data_done.output_done.stream_id = pkt->stream_id;
		data_done.output_done.view_id = pkt->view_id;
		data_done.output_done.timestamp_hi = pkt->time_stamp_hi;
		data_done.output_done.timestamp_lo = pkt->time_stamp_lo;
		data_done.output_done.flags1 = pkt->flags;
		data_done.output_done.mark_target = pkt->mark_target;
		data_done.output_done.mark_data = pkt->mark_data;
		data_done.output_done.stats = pkt->stats;
		data_done.output_done.alloc_len1 = pkt->alloc_len;
		data_done.output_done.filled_len1 = pkt->filled_len;
@@ -909,7 +904,8 @@ static int hfi_process_session_ftb_done(
		data_done.output_done.frame_height = pkt->frame_height;
		data_done.output_done.start_x_coord = pkt->start_x_coord;
		data_done.output_done.start_y_coord = pkt->start_y_coord;
		data_done.output_done.input_tag1 = pkt->input_tag;
		data_done.output_done.input_tag = pkt->input_tag;
		data_done.output_done.input_tag2 = pkt->input_tag2;
		data_done.output_done.picture_type = pkt->picture_type;
		data_done.output_done.packet_buffer1 = pkt->packet_buffer;
		data_done.output_done.extra_data_buffer =
+49 −12
Original line number Diff line number Diff line
@@ -329,6 +329,7 @@ EXPORT_SYMBOL(msm_vidc_release_buffer);
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
{
	struct msm_vidc_inst *inst = instance;
	struct msm_vidc_client_data *client_data = NULL;
	int rc = 0;
	unsigned int i = 0;
	struct buf_queue *q = NULL;
@@ -364,10 +365,17 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
		msm_comm_update_input_cr(inst, b->index, cr);
	}

	if (inst->session_type == MSM_VIDC_DECODER &&
			b->type == INPUT_MPLANE) {
		msm_comm_store_mark_data(&inst->etb_data, b->index,
			b->m.planes[0].reserved[3], b->m.planes[0].reserved[4]);
	if (b->type == INPUT_MPLANE) {
		client_data = msm_comm_store_client_data(inst,
			b->m.planes[0].reserved[3]);
		if (!client_data) {
			dprintk(VIDC_ERR,
				"%s: %x: failed to store client data\n",
				__func__, hash32_ptr(inst->session));
			return -EINVAL;
		}
		msm_comm_store_input_tag(&inst->etb_data, b->index,
			client_data->id, 0);
	}

	q = msm_comm_get_vb2q(inst, b->type);
@@ -393,6 +401,8 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
	int rc = 0;
	unsigned int i = 0;
	struct buf_queue *q = NULL;
	u32 input_tag = 0, input_tag2 = 0;
	bool remove;

	if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
		dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
@@ -421,13 +431,35 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
		b->m.planes[i].reserved[0] = b->m.planes[i].m.fd;
		b->m.planes[i].reserved[1] = b->m.planes[i].data_offset;
	}

	if (inst->session_type == MSM_VIDC_DECODER &&
			b->type == OUTPUT_MPLANE) {
		msm_comm_fetch_mark_data(&inst->fbd_data, b->index,
	/**
	 * Flush handling:
	 * Don't fetch tag - if flush issued at input/output port.
	 * Fetch tag - if atleast 1 ebd received after flush. (Flush_done
	 * event may be notified to userspace even before client
	 * dequeus all buffers at FBD, to avoid this race condition
	 * fetch tag atleast 1 ETB is successfully processed after flush)
	 */
	if (b->type == OUTPUT_MPLANE && !inst->in_flush &&
			!inst->out_flush && inst->clk_data.buffer_counter) {
		rc = msm_comm_fetch_input_tag(&inst->fbd_data, b->index,
				&input_tag, &input_tag2);
		if (rc) {
			dprintk(VIDC_ERR, "Failed to fetch input tag");
			return -EINVAL;
		}
		/**
		 * During flush input_tag & input_tag2 will be zero.
		 * Check before retrieving client data
		 */
		if (input_tag) {
			remove = !(b->flags & V4L2_BUF_FLAG_END_OF_SUBFRAME) &&
					!(b->flags & V4L2_BUF_FLAG_CODECCONFIG);
			msm_comm_fetch_client_data(inst, remove,
				input_tag, input_tag2,
				&b->m.planes[0].reserved[3],
				&b->m.planes[0].reserved[4]);
		}
	}

	return rc;
}
@@ -1552,6 +1584,7 @@ void *msm_vidc_open(int core_id, int session_type)
	INIT_MSM_VIDC_LIST(&inst->cvpbufs);
	INIT_MSM_VIDC_LIST(&inst->refbufs);
	INIT_MSM_VIDC_LIST(&inst->eosbufs);
	INIT_MSM_VIDC_LIST(&inst->client_data);
	INIT_MSM_VIDC_LIST(&inst->etb_data);
	INIT_MSM_VIDC_LIST(&inst->fbd_data);
	INIT_MSM_VIDC_LIST(&inst->window_data);
@@ -1667,6 +1700,7 @@ void *msm_vidc_open(int core_id, int session_type)
	DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
	DEINIT_MSM_VIDC_LIST(&inst->freqs);
	DEINIT_MSM_VIDC_LIST(&inst->input_crs);
	DEINIT_MSM_VIDC_LIST(&inst->client_data);
	DEINIT_MSM_VIDC_LIST(&inst->etb_data);
	DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
	DEINIT_MSM_VIDC_LIST(&inst->window_data);
@@ -1737,9 +1771,11 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
		dprintk(VIDC_ERR,
			"Failed to release persist buffers\n");

	if (msm_comm_release_mark_data(inst))
	if (msm_comm_release_input_tag(inst))
		dprintk(VIDC_ERR,
			"Failed to release mark_data buffers\n");
			"Failed to release input_tag buffers\n");

	msm_comm_release_client_data(inst);

	msm_comm_release_window_data(inst);

@@ -1801,6 +1837,7 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst)
	DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
	DEINIT_MSM_VIDC_LIST(&inst->freqs);
	DEINIT_MSM_VIDC_LIST(&inst->input_crs);
	DEINIT_MSM_VIDC_LIST(&inst->client_data);
	DEINIT_MSM_VIDC_LIST(&inst->etb_data);
	DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
	DEINIT_MSM_VIDC_LIST(&inst->window_data);
+138 −27
Original line number Diff line number Diff line
@@ -2117,8 +2117,10 @@ static void handle_session_flush(enum hal_command_response cmd, void *data)
		goto exit;
	}

	if (flush_type == HAL_FLUSH_ALL)
	if (flush_type == HAL_FLUSH_ALL) {
		msm_comm_release_window_data(inst);
		msm_comm_release_client_data(inst);
	}

	dprintk(VIDC_HIGH,
		"Notify flush complete, flush_type: %x\n", flush_type);
@@ -2650,10 +2652,9 @@ static void handle_fbd(enum hal_command_response cmd, void *data)

	vb->timestamp = (time_usec * NSEC_PER_USEC);

	if (inst->session_type == MSM_VIDC_DECODER) {
		msm_comm_store_mark_data(&inst->fbd_data, vb->index,
			fill_buf_done->mark_data, fill_buf_done->mark_target);
	}
	msm_comm_store_input_tag(&inst->fbd_data, vb->index,
		fill_buf_done->input_tag, fill_buf_done->input_tag2);

	if (inst->session_type == MSM_VIDC_ENCODER) {
		msm_comm_store_filled_length(&inst->fbd_data, vb->index,
			fill_buf_done->filled_len1);
@@ -2674,6 +2675,8 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
		mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
	if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
		mbuf->vvb.flags |= V4L2_BUF_FLAG_DATA_CORRUPT;
	if (fill_buf_done->flags1 & HAL_BUFFERFLAG_ENDOFSUBFRAME)
		mbuf->vvb.flags |= V4L2_BUF_FLAG_END_OF_SUBFRAME;
	switch (fill_buf_done->picture_type) {
	case HFI_PICTURE_TYPE_P:
		mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
@@ -4036,7 +4039,7 @@ int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst)
	list_for_each_entry_safe(binfo, temp, &inst->eosbufs.list, list) {
		data.alloc_len = binfo->smem.size;
		data.device_addr = binfo->smem.device_addr;
		data.clnt_data = data.device_addr;
		data.input_tag = 0;
		data.buffer_type = HAL_BUFFER_INPUT;
		data.filled_len = 0;
		data.offset = 0;
@@ -4183,6 +4186,7 @@ static void populate_frame_data(struct vidc_frame_data *data,
	struct v4l2_format *f = NULL;
	struct vb2_buffer *vb;
	struct vb2_v4l2_buffer *vbuf;
	u32 itag = 0, itag2 = 0;

	if (!inst || !mbuf || !data) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
@@ -4200,7 +4204,7 @@ static void populate_frame_data(struct vidc_frame_data *data,
	data->device_addr = mbuf->smem[0].device_addr;
	data->timestamp = time_usec;
	data->flags = 0;
	data->clnt_data = data->device_addr;
	data->input_tag = 0;

	if (vb->type == INPUT_MPLANE) {
		data->buffer_type = HAL_BUFFER_INPUT;
@@ -4213,10 +4217,10 @@ static void populate_frame_data(struct vidc_frame_data *data,
		if (vbuf->flags & V4L2_BUF_FLAG_CODECCONFIG)
			data->flags |= HAL_BUFFERFLAG_CODECCONFIG;

		if (inst->session_type == MSM_VIDC_DECODER) {
			msm_comm_fetch_mark_data(&inst->etb_data, vb->index,
				&data->mark_data, &data->mark_target);
		}
		msm_comm_fetch_input_tag(&inst->etb_data, vb->index,
			&itag, &itag2);
		data->input_tag = itag;

		f = &inst->fmts[INPUT_PORT].v4l2_fmt;
	} else if (vb->type == OUTPUT_MPLANE) {
		data->buffer_type = msm_comm_get_hal_output_buffer(inst);
@@ -6949,6 +6953,110 @@ bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
	return ret;
}

struct msm_vidc_client_data *msm_comm_store_client_data(
	struct msm_vidc_inst *inst, u32 itag)
{
	struct msm_vidc_client_data *data = NULL;

	if (!inst) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %un",
			__func__, inst, itag);
		return NULL;
	}

	mutex_lock(&inst->client_data.lock);
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data) {
		dprintk(VIDC_ERR, "No memory left to allocate tag data");
		goto exit;
	}

	/**
	 * Special handling, if etb_counter reaches to 2^32 - 1,
	 * then start next value from 1 not 0.
	 */
	if (!inst->etb_counter)
		inst->etb_counter = 1;

	INIT_LIST_HEAD(&data->list);
	data->id =  inst->etb_counter++;
	data->input_tag = itag;
	list_add_tail(&data->list, &inst->client_data.list);

exit:
	mutex_unlock(&inst->client_data.lock);

	return data;
}

void msm_comm_fetch_client_data(struct msm_vidc_inst *inst, bool remove,
	u32 itag, u32 itag2, u32 *otag, u32 *otag2)
{
	struct msm_vidc_client_data *temp, *next;
	bool found_itag = false, found_itag2 = false;

	if (!inst || !otag || !otag2) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %x %x\n",
			__func__, inst, otag, otag2);
		return;
	}

	mutex_lock(&inst->client_data.lock);
	list_for_each_entry_safe(temp, next, &inst->client_data.list, list) {
		if (temp->id == itag) {
			*otag = temp->input_tag;
			if (remove) {
				list_del(&temp->list);
				kfree(temp);
			}
			found_itag = true;
			/**
			 * Some interlace clips, both BF & TP is available in
			 * single ETB buffer. In that case, firmware copies
			 * same input_tag value to both input_tag and
			 * input_tag2 at FBD.
			 */
			if (!itag2 || itag == itag2) {
				found_itag2 = true;
				break;
			}
		} else if (temp->id == itag2) {
			*otag2 = temp->input_tag;
			found_itag2 = true;
			if (remove) {
				list_del(&temp->list);
				kfree(temp);
			}
		}
		if (found_itag && found_itag2)
			break;
	}
	mutex_unlock(&inst->client_data.lock);

	if (!found_itag || !found_itag2) {
		dprintk(VIDC_ERR, "%s: %x: client data not found - %u, %u\n",
			__func__, hash32_ptr(inst->session), itag, itag2);
	}
}

void msm_comm_release_client_data(struct msm_vidc_inst *inst)
{
	struct msm_vidc_client_data *temp, *next;

	if (!inst) {
		dprintk(VIDC_ERR, "%s: invalid params %pK\n",
			__func__, inst);
		return;
	}

	mutex_lock(&inst->client_data.lock);
	list_for_each_entry_safe(temp, next, &inst->client_data.list, list) {
		list_del(&temp->list);
		kfree(temp);
	}
	mutex_unlock(&inst->client_data.lock);
}

void msm_comm_store_filled_length(struct msm_vidc_list *data_list,
		u32 index, u32 filled_length)
{
@@ -7006,8 +7114,8 @@ void msm_comm_fetch_filled_length(struct msm_vidc_list *data_list,
	mutex_unlock(&data_list->lock);
}

void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 mark_data, u32 mark_target)
void msm_comm_store_input_tag(struct msm_vidc_list *data_list,
		u32 index, u32 itag, u32 itag2)
{
	struct msm_vidc_buf_data *pdata = NULL;
	bool found = false;
@@ -7021,8 +7129,8 @@ void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
	mutex_lock(&data_list->lock);
	list_for_each_entry(pdata, &data_list->list, list) {
		if (pdata->index == index) {
			pdata->mark_data = mark_data;
			pdata->mark_target = mark_target;
			pdata->input_tag = itag;
			pdata->input_tag2 = itag2;
			found = true;
			break;
		}
@@ -7035,8 +7143,8 @@ void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
			goto exit;
		}
		pdata->index = index;
		pdata->mark_data = mark_data;
		pdata->mark_target = mark_target;
		pdata->input_tag = itag;
		pdata->input_tag2 = itag2;
		list_add_tail(&pdata->list, &data_list->list);
	}

@@ -7044,32 +7152,35 @@ void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
	mutex_unlock(&data_list->lock);
}

void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 *mark_data, u32 *mark_target)
int msm_comm_fetch_input_tag(struct msm_vidc_list *data_list,
		u32 index, u32 *itag, u32 *itag2)
{
	struct msm_vidc_buf_data *pdata = NULL;
	int rc = 0;

	if (!data_list || !mark_data || !mark_target) {
	if (!data_list || !itag || !itag2) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
			__func__, data_list, mark_data, mark_target);
		return;
			__func__, data_list, itag, itag2);
		return -EINVAL;
	}

	*mark_data = *mark_target = 0;
	*itag = *itag2 = 0;
	mutex_lock(&data_list->lock);
	list_for_each_entry(pdata, &data_list->list, list) {
		if (pdata->index == index) {
			*mark_data = pdata->mark_data;
			*mark_target = pdata->mark_target;
			*itag = pdata->input_tag;
			*itag2 = pdata->input_tag2;
			/* clear after fetch */
			pdata->mark_data = pdata->mark_target = 0;
			pdata->input_tag = pdata->input_tag2 = 0;
			break;
		}
	}
	mutex_unlock(&data_list->lock);

	return rc;
}

int msm_comm_release_mark_data(struct msm_vidc_inst *inst)
int msm_comm_release_input_tag(struct msm_vidc_inst *inst)
{
	struct msm_vidc_buf_data *pdata, *next;

+10 −5
Original line number Diff line number Diff line
@@ -295,11 +295,16 @@ void msm_comm_store_filled_length(struct msm_vidc_list *data_list,
		u32 index, u32 filled_length);
void msm_comm_fetch_filled_length(struct msm_vidc_list *data_list,
		u32 index, u32 *filled_length);
void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 mark_data, u32 mark_target);
void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 *mark_data, u32 *mark_target);
int msm_comm_release_mark_data(struct msm_vidc_inst *inst);
void msm_comm_store_input_tag(struct msm_vidc_list *data_list,
		u32 index, u32 itag, u32 itag2);
int msm_comm_fetch_input_tag(struct msm_vidc_list *data_list,
		u32 index, u32 *itag, u32 *itag2);
int msm_comm_release_input_tag(struct msm_vidc_inst *inst);
struct msm_vidc_client_data *msm_comm_store_client_data(
	struct msm_vidc_inst *inst, u32 itag);
void msm_comm_fetch_client_data(struct msm_vidc_inst *inst, bool remove,
	u32 itag, u32 itag2, u32 *mdata, u32 *mtarget);
void msm_comm_release_client_data(struct msm_vidc_inst *inst);
int msm_comm_qbufs_batch(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf);
int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst,
Loading