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

Commit 092a3b25 authored by Praneeth Paladugu's avatar Praneeth Paladugu Committed by Praveen Chavan
Browse files

msm: vidc: Add support for buffer tags and sub-frame info



   1) Clients send input_tag and output_tag through buffer
      reserved fields. Driver needs to pass them to FW and
      when FW returns them back, send them to client.
   2) Convey sub-frame information to client from FW.

Change-Id: Ia92bca933d18a7795ba17eea9178a4c5de49157b
Signed-off-by: default avatarPraneeth Paladugu <ppaladug@codeaurora.org>
Signed-off-by: default avatarUmesh Pandey <umeshp@codeaurora.org>
Signed-off-by: default avatarPraveen Chavan <pchavan@codeaurora.org>
parent 8b4ff294
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -828,7 +828,7 @@ int create_pkt_cmd_session_etb_decoder(
	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",
@@ -863,7 +863,7 @@ int create_pkt_cmd_session_etb_encoder(
	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;

@@ -899,6 +899,7 @@ int create_pkt_cmd_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
		return -EINVAL;

	pkt->packet_buffer = (u32)output_frame->device_addr;
	pkt->output_tag = output_frame->output_tag;
	pkt->extra_data_buffer = (u32)output_frame->extradata_addr;
	pkt->alloc_len = output_frame->alloc_len;
	pkt->filled_len = output_frame->filled_len;
+24 −3
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -116,6 +116,7 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
	struct hfi_pic_struct *pic_struct;
	struct hfi_buffer_requirements *buf_req;
	struct hfi_index_extradata_input_crop_payload *crop_info;
	struct hfi_dpb_counts *dpb_counts;
	u32 entropy_mode = 0;
	u8 *data_ptr;
	int prop_id;
@@ -216,6 +217,23 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
				data_ptr +=
					sizeof(struct hfi_pic_struct);
				break;
			case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
				data_ptr = data_ptr + sizeof(u32);
				dpb_counts = (struct hfi_dpb_counts *) data_ptr;
				event_notify.max_dpb_count =
					dpb_counts->max_dpb_count;
				event_notify.max_ref_count =
					dpb_counts->max_ref_count;
				event_notify.max_dec_buffering =
					dpb_counts->max_dec_buffering;
				dprintk(VIDC_DBG,
					"DPB Counts: dpb %d ref %d buff %d\n",
						dpb_counts->max_dpb_count,
						dpb_counts->max_ref_count,
						dpb_counts->max_dec_buffering);
				data_ptr +=
					sizeof(struct hfi_pic_struct);
				break;
			case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
				data_ptr = data_ptr + sizeof(u32);
				colour_info =
@@ -313,6 +331,7 @@ static int hfi_process_evt_release_buffer_ref(u32 device_id,
	event_notify.hal_event_type = HAL_EVENT_RELEASE_BUFFER_REFERENCE;
	event_notify.packet_buffer = data->packet_buffer;
	event_notify.extra_data_buffer = data->extra_data_buffer;
	event_notify.output_tag = data->output_tag;

	info->response_type = HAL_SESSION_EVENT_CHANGE;
	info->response.event = event_notify;
@@ -1400,7 +1419,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,
@@ -1532,7 +1551,9 @@ 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_tag1 = pkt->input_tag2;
		data_done.output_done.output_tag = pkt->output_tag;
		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 =
+18 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -505,6 +505,7 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
	struct msm_vidc_inst *inst = instance;
	int rc = 0, i = 0;
	struct buf_queue *q = NULL;
	struct vidc_tag_data tag_data;
	u32 cr = 0;

	if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
@@ -531,6 +532,12 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
			b->m.planes[0].reserved[3], b->m.planes[0].reserved[4]);
	}

	tag_data.index = b->index;
	tag_data.type = b->type;
	tag_data.input_tag = b->m.planes[0].reserved[5];
	tag_data.output_tag = b->m.planes[0].reserved[6];
	msm_comm_store_tags(inst, &tag_data);

	q = msm_comm_get_vb2q(inst, b->type);
	if (!q) {
		dprintk(VIDC_ERR,
@@ -553,6 +560,7 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
	struct msm_vidc_inst *inst = instance;
	int rc = 0, i = 0;
	struct buf_queue *q = NULL;
	struct vidc_tag_data tag_data;

	if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
		dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
@@ -589,6 +597,13 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
			&b->m.planes[0].reserved[4]);
	}

	tag_data.index = b->index;
	tag_data.type = b->type;

	msm_comm_fetch_tags(inst, &tag_data);
	b->m.planes[0].reserved[5] = tag_data.input_tag;
	b->m.planes[0].reserved[6] = tag_data.output_tag;

	return rc;
}
EXPORT_SYMBOL(msm_vidc_dqbuf);
@@ -1856,6 +1871,7 @@ void *msm_vidc_open(int core_id, int session_type)
	INIT_MSM_VIDC_LIST(&inst->scratchbufs);
	INIT_MSM_VIDC_LIST(&inst->freqs);
	INIT_MSM_VIDC_LIST(&inst->input_crs);
	INIT_MSM_VIDC_LIST(&inst->buffer_tags);
	INIT_MSM_VIDC_LIST(&inst->persistbufs);
	INIT_MSM_VIDC_LIST(&inst->pending_getpropq);
	INIT_MSM_VIDC_LIST(&inst->outputbufs);
@@ -1981,6 +1997,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->buffer_tags);
	DEINIT_MSM_VIDC_LIST(&inst->etb_data);
	DEINIT_MSM_VIDC_LIST(&inst->fbd_data);

+120 −5
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1605,7 +1605,7 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data)
}

static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
		int fd, u32 offset)
		int fd, u32 offset, u32 output_tag)
{
	struct v4l2_event buf_event = {0};
	u32 *ptr;
@@ -1614,6 +1614,7 @@ static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
	ptr = (u32 *)buf_event.u.data;
	ptr[0] = fd;
	ptr[1] = offset;
	ptr[2] = output_tag;

	v4l2_event_queue_fh(&inst->event_handler, &buf_event);
}
@@ -1669,6 +1670,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data)
				"%s: data_addr %x, extradata_addr %x not found\n",
				__func__, planes[0], planes[1]);
		} else {
			mbuf->output_tag = event_notify->output_tag;
			handle_release_buffer_reference(inst, mbuf);
			kref_put_mbuf(mbuf);
		}
@@ -1730,6 +1732,9 @@ static void handle_event_change(enum hal_command_response cmd, void *data)
	ptr[10] = msm_comm_get_v4l2_level(
		inst->fmts[OUTPUT_PORT].fourcc,
		event_notify->level);
	ptr[11] = event_notify->max_dpb_count;
	ptr[12] = event_notify->max_ref_count;
	ptr[13] = event_notify->max_dec_buffering;

	dprintk(VIDC_DBG,
		"Event payload: height = %u width = %u profile = %u level = %u\n",
@@ -2474,6 +2479,7 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
	struct vb2_buffer *vb;
	struct msm_vidc_inst *inst;
	struct vidc_hal_ebd *empty_buf_done;
	struct vidc_tag_data tag_data;
	u32 planes[VIDEO_MAX_PLANES] = {0};
	u32 extra_idx = 0;

@@ -2534,6 +2540,13 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
	if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
		vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;

	tag_data.index = vb->index;
	tag_data.input_tag = empty_buf_done->input_tag;
	tag_data.output_tag = empty_buf_done->output_tag;
	tag_data.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;

	msm_comm_store_tags(inst, &tag_data);

	update_recon_stats(inst, &empty_buf_done->recon_stats);
	msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
	/*
@@ -2603,6 +2616,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
	struct msm_vidc_inst *inst;
	struct vb2_buffer *vb;
	struct vidc_hal_fbd *fill_buf_done;
	struct vidc_tag_data tag_data;
	enum hal_buffer buffer_type;
	u64 time_usec = 0;
	u32 planes[VIDEO_MAX_PLANES] = {0};
@@ -2670,6 +2684,13 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
			fill_buf_done->mark_data, fill_buf_done->mark_target);
	}

	tag_data.index = vb->index;
	tag_data.input_tag = fill_buf_done->input_tag;
	tag_data.output_tag = fill_buf_done->output_tag;
	tag_data.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;

	msm_comm_store_tags(inst, &tag_data);

	extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
	if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
		vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
@@ -2685,6 +2706,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_QCOM_BUF_END_OF_SUBFRAME;
	switch (fill_buf_done->picture_type) {
	case HAL_PICTURE_P:
		mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
@@ -4062,7 +4085,6 @@ 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.buffer_type = HAL_BUFFER_INPUT;
		data.filled_len = 0;
		data.offset = 0;
@@ -4181,6 +4203,7 @@ static void populate_frame_data(struct vidc_frame_data *data,
	int extra_idx;
	struct vb2_buffer *vb;
	struct vb2_v4l2_buffer *vbuf;
	struct vidc_tag_data tag_data;

	if (!inst || !mbuf || !data) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
@@ -4198,7 +4221,6 @@ 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;

	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		data->buffer_type = HAL_BUFFER_INPUT;
@@ -4220,6 +4242,14 @@ static void populate_frame_data(struct vidc_frame_data *data,
		data->buffer_type = msm_comm_get_hal_output_buffer(inst);
	}

	tag_data.index = vb->index;
	tag_data.type = vb->type;

	msm_comm_fetch_tags(inst, &tag_data);
	data->input_tag = tag_data.input_tag;
	data->output_tag = tag_data.output_tag;


	extra_idx = EXTRADATA_IDX(vb->num_planes);
	if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
		data->extradata_addr = mbuf->smem[extra_idx].device_addr;
@@ -6667,7 +6697,8 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst,
		/* send RBR event to client */
		msm_vidc_queue_rbr_event(inst,
			mbuf->vvb.vb2_buf.planes[0].m.fd,
			mbuf->vvb.vb2_buf.planes[0].data_offset);
			mbuf->vvb.vb2_buf.planes[0].data_offset,
			mbuf->output_tag);

		/* clear RBR_PENDING flag */
		mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
@@ -6807,6 +6838,90 @@ bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
	return ret;
}

void msm_comm_free_buffer_tags(struct msm_vidc_inst *inst)
{
	struct vidc_tag_data *temp, *next;

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

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

void msm_comm_store_tags(struct msm_vidc_inst *inst,
	struct vidc_tag_data *tag_data)
{

	struct vidc_tag_data *temp, *next;
	struct vidc_tag_data *pdata = NULL;
	bool found = false;

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


	mutex_lock(&inst->buffer_tags.lock);
	list_for_each_entry_safe(temp, next, &inst->buffer_tags.list, list) {
		if (temp->index == tag_data->index &&
				temp->type == tag_data->type) {
			temp->input_tag = tag_data->input_tag;
			temp->output_tag = tag_data->output_tag;
			found = true;
			break;
		}
	}

	if (!found) {
		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
		if (!pdata)  {
			dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
			goto exit;
		}
		pdata->input_tag = tag_data->input_tag;
		pdata->output_tag = tag_data->output_tag;
		pdata->index = tag_data->index;
		pdata->type = tag_data->type;
		list_add_tail(&pdata->list, &inst->buffer_tags.list);
	}

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

void msm_comm_fetch_tags(struct msm_vidc_inst *inst,
	struct vidc_tag_data *tag_data)
{
	struct vidc_tag_data *temp, *next;

	if (!inst || !tag_data) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
				__func__, inst, tag_data);
		return;
	}
	mutex_lock(&inst->buffer_tags.lock);
	list_for_each_entry_safe(temp, next, &inst->buffer_tags.list, list) {
		if (temp->index == tag_data->index &&
				temp->type == tag_data->type) {
			tag_data->input_tag = temp->input_tag;
			tag_data->output_tag = temp->output_tag;
			break;
		}
	}
	mutex_unlock(&inst->buffer_tags.lock);
}

void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 mark_data, u32 mark_target)
{
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -232,6 +232,11 @@ bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
		u32 type, u32 *planes, u32 i);
bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
		u32 type, u32 *planes);
void msm_comm_store_tags(struct msm_vidc_inst *inst,
		struct vidc_tag_data *tag_data);
void msm_comm_fetch_tags(struct msm_vidc_inst *inst,
		struct vidc_tag_data *tag_data);
void msm_comm_free_buffer_tags(struct msm_vidc_inst *inst);
int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf);
int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
Loading