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

Commit 622a9032 authored by Arun Menon's avatar Arun Menon Committed by Matt Wagantall
Browse files

msm: vidc: Add support for session continue



Venus 3x firmware halts execution after raising a
a sequence change event to v4l2 driver. This change
is needed for firmware to resume execution after
it raises a sequence change event.
Before session continue command, the firmware expects
driver to always set the minimum buffer size negotiated
with v4l2 client, and the actual buffer count. Firmware
will use this information to check for buffer sufficiency.

Change-Id: Ib59cfcbdc22008ad842664c722f404f669a23588
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent 8d056a2f
Loading
Loading
Loading
Loading
+35 −6
Original line number Diff line number Diff line
@@ -368,6 +368,34 @@ int create_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
	if (!pkt)
		return -EINVAL;

	/*
	 * Legacy packetization should skip sending any 3xx specific session
	 * cmds. Add 3xx specific packetization to the switch case below.
	 */
	switch (pkt_type) {
	case HFI_CMD_SESSION_CONTINUE:
		dprintk(VIDC_INFO,
			"%s - skip sending %x for legacy hfi\n",
			__func__, pkt_type);
		return -EPERM;
	default:
		break;
	}

	pkt->size = sizeof(struct vidc_hal_session_cmd_pkt);
	pkt->packet_type = pkt_type;
	pkt->session_id = hash32_ptr(session);

	return rc;
}

int create_3x_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
			int pkt_type, struct hal_session *session)
{
	int rc = 0;
	if (!pkt)
		return -EINVAL;

	pkt->size = sizeof(struct vidc_hal_session_cmd_pkt);
	pkt->packet_type = pkt_type;
	pkt->session_id = hash32_ptr(session);
@@ -990,17 +1018,17 @@ int create_pkt_cmd_session_set_property(

		break;
	}
	case HAL_PARAM_BUFFER_SIZE_ACTUAL:
	case HAL_PARAM_BUFFER_SIZE_MINIMUM:
	{
		struct hfi_buffer_size_actual *hfi;
		struct hal_buffer_size_actual *prop =
			(struct hal_buffer_size_actual *) pdata;
		struct hfi_buffer_size_minimum *hfi;
		struct hal_buffer_size_minimum *prop =
			(struct hal_buffer_size_minimum *) pdata;
		u32 buffer_type;

		pkt->rg_property_data[0] =
			HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
			HFI_PROPERTY_PARAM_BUFFER_SIZE_MINIMUM;

		hfi = (struct hfi_buffer_size_actual *)
		hfi = (struct hfi_buffer_size_minimum *)
			&pkt->rg_property_data[1];
		hfi->buffer_size = prop->buffer_size;

@@ -2083,6 +2111,7 @@ struct hfi_packetization_ops *get_venus_3x_ops(void)
	/* Override new HFI functions for HFI_PACKETIZATION_3XX here. */
	hfi_venus_3x.session_set_property =
		create_3x_pkt_cmd_session_set_property;
	hfi_venus_3x.session_cmd = create_3x_pkt_cmd_session_cmd;

	return &hfi_venus_3x;
}
+65 −29
Original line number Diff line number Diff line
@@ -556,6 +556,11 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {

#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)

static int set_buffer_size(struct msm_vidc_inst *inst,
				u32 buffer_size, enum hal_buffer buffer_type);
static int update_output_buffer_size(struct msm_vidc_inst *inst,
		struct v4l2_format *f, int num_planes);

static u32 get_frame_size_nv12(int plane,
					u32 height, u32 width)
{
@@ -1124,6 +1129,13 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
		for (i = 0; i < fmt->num_planes; ++i)
			inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] =
				f->fmt.pix_mp.plane_fmt[i].sizeimage;
		rc = update_output_buffer_size(inst, f, fmt->num_planes);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s - failed to update buffer size: %d\n",
				__func__, rc);
			goto exit;
		}
	}

	if (stride && scanlines) {
@@ -1207,7 +1219,7 @@ static int set_buffer_size(struct msm_vidc_inst *inst,
{
	int rc = 0;
	struct hfi_device *hdev;
	struct hal_buffer_size_actual buffer_size_actual;
	struct hal_buffer_size_minimum b;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -1217,14 +1229,14 @@ static int set_buffer_size(struct msm_vidc_inst *inst,
	hdev = inst->core->device;

	dprintk(VIDC_DBG,
		"Set actual buffer size = %d for buffer type %d to fw\n",
		"Set minimum buffer size = %d for buffer type %d to fw\n",
		buffer_size, buffer_type);

	buffer_size_actual.buffer_type = buffer_type;
	buffer_size_actual.buffer_size = buffer_size;
	b.buffer_type = buffer_type;
	b.buffer_size = buffer_size;
	rc = call_hfi_op(hdev, session_set_property,
			 inst->session, HAL_PARAM_BUFFER_SIZE_ACTUAL,
			 &buffer_size_actual);
			 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
			 &b);
	if (rc)
		dprintk(VIDC_ERR,
			"%s - failed to set actual buffer size %u on firmware\n",
@@ -1233,31 +1245,31 @@ static int set_buffer_size(struct msm_vidc_inst *inst,
}

static int update_output_buffer_size(struct msm_vidc_inst *inst,
		struct v4l2_format *f, struct msm_vidc_format *fmt)
		struct v4l2_format *f, int num_planes)
{
	int rc = 0, i = 0;
	struct hal_buffer_requirements *bufreq;

	if (!inst || !f || !fmt)
	if (!inst || !f)
		return -EINVAL;

	/*
	 * Compare set buffer size and update to firmware if it's bigger
	 * then firmware returned buffer size.
	 * Firmware expects driver to always set the minimum buffer
	 * size negotiated with the v4l2 client. Firmware will use this
	 * size to check for buffer sufficiency in dynamic buffer mode.
	 */
	for (i = 0; i < fmt->num_planes; ++i) {
	for (i = 0; i < num_planes; ++i) {
		enum hal_buffer type = msm_comm_get_hal_output_buffer(inst);

		if (EXTRADATA_IDX(fmt->num_planes) &&
			i == EXTRADATA_IDX(fmt->num_planes)) {
			type = HAL_BUFFER_EXTRADATA_OUTPUT;
		}
		if (EXTRADATA_IDX(num_planes) &&
			i == EXTRADATA_IDX(num_planes))
			continue;

		bufreq = get_buff_req_buffer(inst, type);
		if (!bufreq)
			goto exit;

		if (f->fmt.pix_mp.plane_fmt[i].sizeimage >
		if (f->fmt.pix_mp.plane_fmt[i].sizeimage >=
			bufreq->buffer_size) {
			rc = set_buffer_size(inst,
				f->fmt.pix_mp.plane_fmt[i].sizeimage, type);
@@ -1273,11 +1285,11 @@ static int update_output_buffer_size(struct msm_vidc_inst *inst,
			"Failed to get buf req, %d\n", rc);

	/* Read back updated firmware size */
	for (i = 0; i < fmt->num_planes; ++i) {
	for (i = 0; i < num_planes; ++i) {
		enum hal_buffer type = msm_comm_get_hal_output_buffer(inst);

		if (EXTRADATA_IDX(fmt->num_planes) &&
			i == EXTRADATA_IDX(fmt->num_planes)) {
		if (EXTRADATA_IDX(num_planes) &&
			i == EXTRADATA_IDX(num_planes)) {
			type = HAL_BUFFER_EXTRADATA_OUTPUT;
		}

@@ -1391,7 +1403,8 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
					get_frame_size(inst, fmt, f->type, i);
			}
		} else {
			rc = update_output_buffer_size(inst, f, fmt);
			rc = update_output_buffer_size(inst, f,
				fmt->num_planes);
			if (rc) {
				dprintk(VIDC_ERR,
					"%s - failed to update buffer size: %d\n",
@@ -1607,14 +1620,14 @@ static int msm_vdec_queue_setup(struct vb2_queue *q,
		}

		*num_buffers = max(*num_buffers, bufreq->buffer_count_min);
		if (*num_buffers != bufreq->buffer_count_actual) {
		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
		new_buf_count.buffer_type =
			msm_comm_get_hal_output_buffer(inst);
		new_buf_count.buffer_count_actual = *num_buffers;
		dprintk(VIDC_DBG, "Set actual output buffer count: %d\n",
				*num_buffers);
		rc = call_hfi_op(hdev, session_set_property,
			inst->session, property_id, &new_buf_count);
		}

		if (*num_buffers != bufreq->buffer_count_actual) {
			rc = msm_comm_try_get_bufreqs(inst);
@@ -1656,7 +1669,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
	struct list_head *ptr, *next;

	hdev = inst->core->device;
	inst->in_reconfig = false;

	if (msm_comm_get_stream_output_mode(inst) ==
		HAL_VIDEO_DECODER_SECONDARY)
		rc = msm_vidc_check_scaling_supported(inst);
@@ -1687,6 +1700,29 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
		}
	}

	/*
	 * For seq_changed_insufficient, driver should set session_continue
	 * to firmware after the following sequence
	 * - driver raises insufficient event to v4l2 client
	 * - all output buffers have been flushed and freed
	 * - v4l2 client queries buffer requirements and splits/combines OPB-DPB
	 * - v4l2 client sets new set of buffers to firmware
	 * - v4l2 client issues CONTINUE to firmware to resume decoding of
	 *   submitted ETBs.
	 */
	if (inst->in_reconfig) {
		dprintk(VIDC_DBG, "send session_continue after reconfig\n");
		rc = call_hfi_op(hdev, session_continue,
			(void *) inst->session);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s - failed to send session_continue\n",
				__func__);
			goto fail_start;
		}
	}
	inst->in_reconfig = false;

	msm_comm_scale_clocks_and_bus(inst);

	rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
+10 −0
Original line number Diff line number Diff line
@@ -2568,6 +2568,9 @@ static int venus_hfi_send_session_cmd(void *session_id,

	rc = call_hfi_pkt_op(device, session_cmd,
			&pkt, pkt_type, session);
	if (rc == -EPERM)
		return 0;

	if (rc) {
		dprintk(VIDC_ERR, "send session cmd: create pkt failed\n");
		goto err_create_pkt;
@@ -2691,6 +2694,12 @@ static int venus_hfi_session_start(void *sess)
		HFI_CMD_SESSION_START);
}

static int venus_hfi_session_continue(void *sess)
{
	return venus_hfi_send_session_cmd(sess,
		HFI_CMD_SESSION_CONTINUE);
}

static int venus_hfi_session_stop(void *sess)
{
	return venus_hfi_send_session_cmd(sess,
@@ -4167,6 +4176,7 @@ static void venus_init_hfi_callbacks(struct hfi_device *hdev)
	hdev->session_load_res = venus_hfi_session_load_res;
	hdev->session_release_res = venus_hfi_session_release_res;
	hdev->session_start = venus_hfi_session_start;
	hdev->session_continue = venus_hfi_session_continue;
	hdev->session_stop = venus_hfi_session_stop;
	hdev->session_etb = venus_hfi_session_etb;
	hdev->session_ftb = venus_hfi_session_ftb;
+9 −2
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ struct hfi_extradata_header {
	(HFI_PROPERTY_PARAM_OX_START + 0x00A)
#define  HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED	\
	(HFI_PROPERTY_PARAM_OX_START + 0x00B)
#define  HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL			\
#define  HFI_PROPERTY_PARAM_BUFFER_SIZE_MINIMUM			\
	(HFI_PROPERTY_PARAM_OX_START + 0x00C)

#define HFI_PROPERTY_CONFIG_OX_START					\
@@ -256,7 +256,7 @@ struct hfi_buffer_count_actual {
	u32 buffer_count_actual;
};

struct hfi_buffer_size_actual {
struct hfi_buffer_size_minimum {
	u32 buffer_type;
	u32 buffer_size;
};
@@ -371,6 +371,7 @@ struct hfi_uncompressed_plane_actual_constraints_info {
	(HFI_CMD_SESSION_OX_START + 0x00B)
#define HFI_CMD_SESSION_RELEASE_RESOURCES	\
	(HFI_CMD_SESSION_OX_START + 0x00C)
#define  HFI_CMD_SESSION_CONTINUE  (HFI_CMD_SESSION_OX_START + 0x00D)

#define HFI_MSG_SYS_OX_START			\
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
@@ -854,6 +855,12 @@ struct hfi_extradata_recovery_point_sei_payload {
	u32 flag;
};

struct hfi_cmd_session_continue_packet {
	u32 size;
	u32 packet_type;
	u32 session_id;
};

struct hal_session {
	struct list_head list;
	void *session_id;
+3 −2
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ enum hal_property {
	HAL_PARAM_FRAME_SIZE,
	HAL_CONFIG_REALTIME,
	HAL_PARAM_BUFFER_COUNT_ACTUAL,
	HAL_PARAM_BUFFER_SIZE_ACTUAL,
	HAL_PARAM_BUFFER_SIZE_MINIMUM,
	HAL_PARAM_NAL_STREAM_FORMAT_SELECT,
	HAL_PARAM_VDEC_OUTPUT_ORDER,
	HAL_PARAM_VDEC_PICTURE_TYPE_DECODE,
@@ -576,7 +576,7 @@ struct hal_buffer_count_actual {
	u32 buffer_count_actual;
};

struct hal_buffer_size_actual {
struct hal_buffer_size_minimum {
	enum hal_buffer buffer_type;
	u32 buffer_size;
};
@@ -1355,6 +1355,7 @@ struct hfi_device {
	int (*session_load_res)(void *sess);
	int (*session_release_res)(void *sess);
	int (*session_start)(void *sess);
	int (*session_continue)(void *sess);
	int (*session_stop)(void *sess);
	int (*session_etb)(void *sess,
			struct vidc_frame_data *input_frame);