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

Commit 79ca953a authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: handle release ref events for dynamic buffers



For dynamic output buffers, firmware can hold on to a
output buffer reference after releasing it to
driver. The buffer is marked as read only and sent
back to client. The driver maintains the reference
of this buffer and decrements it when firmware
sends the release reference event. The client is
notified of the release reference event.

Change-Id: Ie3c014af255e09f6dac9b3b853c9994b97d830b6
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent b8b91fe7
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -163,6 +163,39 @@ static void hfi_process_sess_evt_seq_changed(
	callback(VIDC_EVENT_CHANGE, &cmd_done);
}

static void hfi_process_evt_release_buffer_ref(
		msm_vidc_callback callback, u32 device_id,
		struct hfi_msg_event_notify_packet *pkt)
{
	struct msm_vidc_cb_cmd_done cmd_done = {0};
	struct msm_vidc_cb_event event_notify = {0};

	struct hfi_msg_release_buffer_ref_event_packet *data;

	dprintk(VIDC_DBG, "RECEIVED:EVENT_NOTIFY - release_buffer_reference");
	if (sizeof(struct hfi_msg_event_notify_packet)
		> pkt->size) {
		dprintk(VIDC_ERR, "hal_process_session_init_done:bad_pkt_size");
		return;
	}

	data = (struct hfi_msg_release_buffer_ref_event_packet *)
				pkt->rg_ext_event_data;


	cmd_done.device_id = device_id;
	cmd_done.session_id =
		((struct hal_session *)data->output_tag)->session_id;
	cmd_done.status = VIDC_ERR_NONE;
	cmd_done.size = sizeof(struct msm_vidc_cb_event);

	event_notify.hal_event_type = HAL_EVENT_RELEASE_BUFFER_REFERENCE;
	event_notify.packet_buffer = data->packet_buffer;
	event_notify.exra_data_buffer = data->exra_data_buffer;
	cmd_done.data = &event_notify;
	callback(VIDC_EVENT_CHANGE, &cmd_done);
}

static void hfi_process_sys_error(
		msm_vidc_callback callback, u32 device_id)
{
@@ -217,6 +250,10 @@ static void hfi_process_event_notify(
	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
		break;
	case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
		dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE\n");
		hfi_process_evt_release_buffer_ref(callback, device_id, pkt);
		break;
	default:
		dprintk(VIDC_WARN, "hal_process_event_notify:unkown_event_id");
		break;
+56 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
		V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT
#define V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT \
		V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT
#define V4L2_EVENT_RELEASE_BUFFER_REFERENCE \
		V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE

#define NUM_MBS_PER_SEC(__height, __width, __fps) ({\
	(__height >> 4) * (__width >> 4) * __fps; \
@@ -483,6 +485,60 @@ static void handle_event_change(enum command_response cmd, void *data)
		case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
			event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
			break;
		case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
			{
				struct v4l2_event buf_event = {0};
				struct buffer_info *binfo = NULL;
				u32 *ptr = NULL;

				dprintk(VIDC_DBG,
					"%s - inst: %p buffer: %p extra: %p\n",
					__func__, inst,
					event_notify->packet_buffer,
					event_notify->exra_data_buffer);

				/*
				* Get the buffer_info entry for the
				* device address.
				*/
				binfo = device_to_uvaddr(inst,
					&inst->registered_bufs,
					(u32)event_notify->packet_buffer);
				if (!binfo) {
					dprintk(VIDC_ERR,
						"%s buffer not found in registered list\n",
						__func__);
					return;
				}

				/* Fill event data to be sent to client*/
				buf_event.type =
					V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
				ptr = (u32 *)buf_event.u.data;
				ptr[0] = binfo->fd[0];
				ptr[1] = binfo->buff_off[0];

				dprintk(VIDC_DBG,
					"RELEASE REFERENCE EVENT FROM F/W - fd = %d offset = %d\n",
					ptr[0], ptr[1]);

				/* Decrement buffer reference count*/
				buf_ref_put(inst, binfo);

				/*
				* Release buffer and remove from list
				* if reference goes to zero.
				*/
				if (unmap_and_deregister_buf(inst, binfo))
					dprintk(VIDC_ERR,
					"%s: buffer unmap failed\n", __func__);

				/*send event to client*/
				v4l2_event_queue_fh(&inst->event_handler,
					&buf_event);
				wake_up(&inst->kernel_event_queue);
				return;
			}
		default:
			break;
		}
+3 −0
Original line number Diff line number Diff line
@@ -286,8 +286,11 @@ struct buffer_info {
struct buffer_info *device_to_uvaddr(struct msm_vidc_inst *inst,
			struct list_head *list, u32 device_addr);
int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo);
int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo);
int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
				struct buffer_info *binfo);
int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
			struct buffer_info *binfo);
int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
			struct buffer_info *binfo);
#endif
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
#define HFI_EVENT_RELEASE_BUFFER_REFERENCE (HFI_OX_BASE + 0x6)

#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
	(HFI_OX_BASE + 0x1)
+3 −0
Original line number Diff line number Diff line
@@ -885,6 +885,7 @@ enum hal_flush {
enum hal_event_type {
	HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES,
	HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES,
	HAL_EVENT_RELEASE_BUFFER_REFERENCE,
	HAL_UNUSED_SEQCHG = 0x10000000,
};

@@ -953,6 +954,8 @@ struct msm_vidc_cb_event {
	u32 height;
	u32 width;
	u32 hal_event_type;
	u8 *packet_buffer;
	u8 *exra_data_buffer;
};

/* Data callback structure */
Loading