197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
209c2845eSStanimir Varbanov /*
309c2845eSStanimir Varbanov  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
409c2845eSStanimir Varbanov  * Copyright (C) 2017 Linaro Ltd.
509c2845eSStanimir Varbanov  */
609c2845eSStanimir Varbanov #include <linux/hash.h>
709c2845eSStanimir Varbanov #include <linux/list.h>
809c2845eSStanimir Varbanov #include <linux/slab.h>
9d566e78dSDikshita Agarwal #include <linux/soc/qcom/smem.h>
1009c2845eSStanimir Varbanov #include <media/videobuf2-v4l2.h>
1109c2845eSStanimir Varbanov 
1209c2845eSStanimir Varbanov #include "core.h"
1309c2845eSStanimir Varbanov #include "hfi.h"
1409c2845eSStanimir Varbanov #include "hfi_helper.h"
1509c2845eSStanimir Varbanov #include "hfi_msgs.h"
161a73374aSStanimir Varbanov #include "hfi_parser.h"
1709c2845eSStanimir Varbanov 
18d566e78dSDikshita Agarwal #define SMEM_IMG_VER_TBL	469
19d566e78dSDikshita Agarwal #define VER_STR_SZ		128
20d566e78dSDikshita Agarwal #define SMEM_IMG_OFFSET_VENUS	(14 * 128)
21d566e78dSDikshita Agarwal 
event_seq_changed(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)2209c2845eSStanimir Varbanov static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
2309c2845eSStanimir Varbanov 			      struct hfi_msg_event_notify_pkt *pkt)
2409c2845eSStanimir Varbanov {
259eb2146eSStanimir Varbanov 	enum hfi_version ver = core->res->hfi_version;
2609c2845eSStanimir Varbanov 	struct hfi_event_data event = {0};
2709c2845eSStanimir Varbanov 	int num_properties_changed;
2809c2845eSStanimir Varbanov 	struct hfi_framesize *frame_sz;
2909c2845eSStanimir Varbanov 	struct hfi_profile_level *profile_level;
309eb2146eSStanimir Varbanov 	struct hfi_bit_depth *pixel_depth;
319eb2146eSStanimir Varbanov 	struct hfi_pic_struct *pic_struct;
329eb2146eSStanimir Varbanov 	struct hfi_colour_space *colour_info;
339eb2146eSStanimir Varbanov 	struct hfi_buffer_requirements *bufreq;
349eb2146eSStanimir Varbanov 	struct hfi_extradata_input_crop *crop;
3516545aa3SDikshita Agarwal 	struct hfi_dpb_counts *dpb_count;
3609c2845eSStanimir Varbanov 	u8 *data_ptr;
3709c2845eSStanimir Varbanov 	u32 ptype;
3809c2845eSStanimir Varbanov 
3909c2845eSStanimir Varbanov 	inst->error = HFI_ERR_NONE;
4009c2845eSStanimir Varbanov 
4109c2845eSStanimir Varbanov 	switch (pkt->event_data1) {
4209c2845eSStanimir Varbanov 	case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
4309c2845eSStanimir Varbanov 	case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
4409c2845eSStanimir Varbanov 		break;
4509c2845eSStanimir Varbanov 	default:
4609c2845eSStanimir Varbanov 		inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
4709c2845eSStanimir Varbanov 		goto done;
4809c2845eSStanimir Varbanov 	}
4909c2845eSStanimir Varbanov 
5009c2845eSStanimir Varbanov 	event.event_type = pkt->event_data1;
5109c2845eSStanimir Varbanov 
5209c2845eSStanimir Varbanov 	num_properties_changed = pkt->event_data2;
5309c2845eSStanimir Varbanov 	if (!num_properties_changed) {
5409c2845eSStanimir Varbanov 		inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
5509c2845eSStanimir Varbanov 		goto done;
5609c2845eSStanimir Varbanov 	}
5709c2845eSStanimir Varbanov 
5809c2845eSStanimir Varbanov 	data_ptr = (u8 *)&pkt->ext_event_data[0];
5909c2845eSStanimir Varbanov 	do {
6009c2845eSStanimir Varbanov 		ptype = *((u32 *)data_ptr);
6109c2845eSStanimir Varbanov 		switch (ptype) {
6209c2845eSStanimir Varbanov 		case HFI_PROPERTY_PARAM_FRAME_SIZE:
6309c2845eSStanimir Varbanov 			data_ptr += sizeof(u32);
6409c2845eSStanimir Varbanov 			frame_sz = (struct hfi_framesize *)data_ptr;
6509c2845eSStanimir Varbanov 			event.width = frame_sz->width;
6609c2845eSStanimir Varbanov 			event.height = frame_sz->height;
67ea8afbabSStanimir Varbanov 			data_ptr += sizeof(*frame_sz);
6809c2845eSStanimir Varbanov 			break;
6909c2845eSStanimir Varbanov 		case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
7009c2845eSStanimir Varbanov 			data_ptr += sizeof(u32);
7109c2845eSStanimir Varbanov 			profile_level = (struct hfi_profile_level *)data_ptr;
7209c2845eSStanimir Varbanov 			event.profile = profile_level->profile;
7309c2845eSStanimir Varbanov 			event.level = profile_level->level;
74ea8afbabSStanimir Varbanov 			data_ptr += sizeof(*profile_level);
7509c2845eSStanimir Varbanov 			break;
769eb2146eSStanimir Varbanov 		case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
779eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
789eb2146eSStanimir Varbanov 			pixel_depth = (struct hfi_bit_depth *)data_ptr;
799eb2146eSStanimir Varbanov 			event.bit_depth = pixel_depth->bit_depth;
809eb2146eSStanimir Varbanov 			data_ptr += sizeof(*pixel_depth);
819eb2146eSStanimir Varbanov 			break;
829eb2146eSStanimir Varbanov 		case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
839eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
849eb2146eSStanimir Varbanov 			pic_struct = (struct hfi_pic_struct *)data_ptr;
859eb2146eSStanimir Varbanov 			event.pic_struct = pic_struct->progressive_only;
869eb2146eSStanimir Varbanov 			data_ptr += sizeof(*pic_struct);
879eb2146eSStanimir Varbanov 			break;
889eb2146eSStanimir Varbanov 		case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
899eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
909eb2146eSStanimir Varbanov 			colour_info = (struct hfi_colour_space *)data_ptr;
919eb2146eSStanimir Varbanov 			event.colour_space = colour_info->colour_space;
929eb2146eSStanimir Varbanov 			data_ptr += sizeof(*colour_info);
939eb2146eSStanimir Varbanov 			break;
949eb2146eSStanimir Varbanov 		case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
959eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
969eb2146eSStanimir Varbanov 			event.entropy_mode = *(u32 *)data_ptr;
979eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
989eb2146eSStanimir Varbanov 			break;
999eb2146eSStanimir Varbanov 		case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
1009eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
1019eb2146eSStanimir Varbanov 			bufreq = (struct hfi_buffer_requirements *)data_ptr;
102bbfc89e6SKonrad Dybcio 			event.buf_count = hfi_bufreq_get_count_min(bufreq, ver);
1039eb2146eSStanimir Varbanov 			data_ptr += sizeof(*bufreq);
1049eb2146eSStanimir Varbanov 			break;
1059eb2146eSStanimir Varbanov 		case HFI_INDEX_EXTRADATA_INPUT_CROP:
1069eb2146eSStanimir Varbanov 			data_ptr += sizeof(u32);
1079eb2146eSStanimir Varbanov 			crop = (struct hfi_extradata_input_crop *)data_ptr;
1089eb2146eSStanimir Varbanov 			event.input_crop.left = crop->left;
1099eb2146eSStanimir Varbanov 			event.input_crop.top = crop->top;
1109eb2146eSStanimir Varbanov 			event.input_crop.width = crop->width;
1119eb2146eSStanimir Varbanov 			event.input_crop.height = crop->height;
1129eb2146eSStanimir Varbanov 			data_ptr += sizeof(*crop);
1139eb2146eSStanimir Varbanov 			break;
11416545aa3SDikshita Agarwal 		case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
11516545aa3SDikshita Agarwal 			data_ptr += sizeof(u32);
11616545aa3SDikshita Agarwal 			dpb_count = (struct hfi_dpb_counts *)data_ptr;
11716545aa3SDikshita Agarwal 			event.buf_count = dpb_count->fw_min_cnt;
11816545aa3SDikshita Agarwal 			data_ptr += sizeof(*dpb_count);
11916545aa3SDikshita Agarwal 			break;
12009c2845eSStanimir Varbanov 		default:
12109c2845eSStanimir Varbanov 			break;
12209c2845eSStanimir Varbanov 		}
12309c2845eSStanimir Varbanov 		num_properties_changed--;
12409c2845eSStanimir Varbanov 	} while (num_properties_changed > 0);
12509c2845eSStanimir Varbanov 
12609c2845eSStanimir Varbanov done:
12709c2845eSStanimir Varbanov 	inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
12809c2845eSStanimir Varbanov }
12909c2845eSStanimir Varbanov 
event_release_buffer_ref(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)13009c2845eSStanimir Varbanov static void event_release_buffer_ref(struct venus_core *core,
13109c2845eSStanimir Varbanov 				     struct venus_inst *inst,
13209c2845eSStanimir Varbanov 				     struct hfi_msg_event_notify_pkt *pkt)
13309c2845eSStanimir Varbanov {
13409c2845eSStanimir Varbanov 	struct hfi_event_data event = {0};
13509c2845eSStanimir Varbanov 	struct hfi_msg_event_release_buffer_ref_pkt *data;
13609c2845eSStanimir Varbanov 
13709c2845eSStanimir Varbanov 	data = (struct hfi_msg_event_release_buffer_ref_pkt *)
13809c2845eSStanimir Varbanov 		pkt->ext_event_data;
13909c2845eSStanimir Varbanov 
14009c2845eSStanimir Varbanov 	event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
14109c2845eSStanimir Varbanov 	event.packet_buffer = data->packet_buffer;
14209c2845eSStanimir Varbanov 	event.extradata_buffer = data->extradata_buffer;
14309c2845eSStanimir Varbanov 	event.tag = data->output_tag;
14409c2845eSStanimir Varbanov 
14509c2845eSStanimir Varbanov 	inst->error = HFI_ERR_NONE;
14609c2845eSStanimir Varbanov 	inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
14709c2845eSStanimir Varbanov }
14809c2845eSStanimir Varbanov 
event_sys_error(struct venus_core * core,u32 event,struct hfi_msg_event_notify_pkt * pkt)14909c2845eSStanimir Varbanov static void event_sys_error(struct venus_core *core, u32 event,
15009c2845eSStanimir Varbanov 			    struct hfi_msg_event_notify_pkt *pkt)
15109c2845eSStanimir Varbanov {
15209c2845eSStanimir Varbanov 	if (pkt)
1538c91dc08SStanimir Varbanov 		dev_dbg(core->dev, VDBGH
15409c2845eSStanimir Varbanov 			"sys error (session id:%x, data1:%x, data2:%x)\n",
15509c2845eSStanimir Varbanov 			pkt->shdr.session_id, pkt->event_data1,
15609c2845eSStanimir Varbanov 			pkt->event_data2);
15709c2845eSStanimir Varbanov 
15809c2845eSStanimir Varbanov 	core->core_ops->event_notify(core, event);
15909c2845eSStanimir Varbanov }
16009c2845eSStanimir Varbanov 
16109c2845eSStanimir Varbanov static void
event_session_error(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)16209c2845eSStanimir Varbanov event_session_error(struct venus_core *core, struct venus_inst *inst,
16309c2845eSStanimir Varbanov 		    struct hfi_msg_event_notify_pkt *pkt)
16409c2845eSStanimir Varbanov {
16509c2845eSStanimir Varbanov 	struct device *dev = core->dev;
16609c2845eSStanimir Varbanov 
1678c91dc08SStanimir Varbanov 	dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n",
16809c2845eSStanimir Varbanov 		pkt->event_data1, pkt->shdr.session_id);
16909c2845eSStanimir Varbanov 
17009c2845eSStanimir Varbanov 	if (!inst)
17109c2845eSStanimir Varbanov 		return;
17209c2845eSStanimir Varbanov 
17309c2845eSStanimir Varbanov 	switch (pkt->event_data1) {
17409c2845eSStanimir Varbanov 	/* non fatal session errors */
17509c2845eSStanimir Varbanov 	case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
17609c2845eSStanimir Varbanov 	case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
17709c2845eSStanimir Varbanov 	case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
17809c2845eSStanimir Varbanov 	case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
17909c2845eSStanimir Varbanov 		inst->error = HFI_ERR_NONE;
18009c2845eSStanimir Varbanov 		break;
18109c2845eSStanimir Varbanov 	default:
18209c2845eSStanimir Varbanov 		dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
18309c2845eSStanimir Varbanov 			pkt->event_data1, pkt->event_data2,
18409c2845eSStanimir Varbanov 			pkt->shdr.session_id);
18509c2845eSStanimir Varbanov 
18609c2845eSStanimir Varbanov 		inst->error = pkt->event_data1;
18709c2845eSStanimir Varbanov 		inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
18809c2845eSStanimir Varbanov 		break;
18909c2845eSStanimir Varbanov 	}
19009c2845eSStanimir Varbanov }
19109c2845eSStanimir Varbanov 
hfi_event_notify(struct venus_core * core,struct venus_inst * inst,void * packet)19209c2845eSStanimir Varbanov static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
19309c2845eSStanimir Varbanov 			     void *packet)
19409c2845eSStanimir Varbanov {
19509c2845eSStanimir Varbanov 	struct hfi_msg_event_notify_pkt *pkt = packet;
19609c2845eSStanimir Varbanov 
19709c2845eSStanimir Varbanov 	if (!packet)
19809c2845eSStanimir Varbanov 		return;
19909c2845eSStanimir Varbanov 
20009c2845eSStanimir Varbanov 	switch (pkt->event_id) {
20109c2845eSStanimir Varbanov 	case HFI_EVENT_SYS_ERROR:
20209c2845eSStanimir Varbanov 		event_sys_error(core, EVT_SYS_ERROR, pkt);
20309c2845eSStanimir Varbanov 		break;
20409c2845eSStanimir Varbanov 	case HFI_EVENT_SESSION_ERROR:
20509c2845eSStanimir Varbanov 		event_session_error(core, inst, pkt);
20609c2845eSStanimir Varbanov 		break;
20709c2845eSStanimir Varbanov 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
20809c2845eSStanimir Varbanov 		event_seq_changed(core, inst, pkt);
20909c2845eSStanimir Varbanov 		break;
21009c2845eSStanimir Varbanov 	case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
21109c2845eSStanimir Varbanov 		event_release_buffer_ref(core, inst, pkt);
21209c2845eSStanimir Varbanov 		break;
21309c2845eSStanimir Varbanov 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
21409c2845eSStanimir Varbanov 		break;
21509c2845eSStanimir Varbanov 	default:
21609c2845eSStanimir Varbanov 		break;
21709c2845eSStanimir Varbanov 	}
21809c2845eSStanimir Varbanov }
21909c2845eSStanimir Varbanov 
hfi_sys_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)22009c2845eSStanimir Varbanov static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
22109c2845eSStanimir Varbanov 			      void *packet)
22209c2845eSStanimir Varbanov {
22309c2845eSStanimir Varbanov 	struct hfi_msg_sys_init_done_pkt *pkt = packet;
2241a73374aSStanimir Varbanov 	int rem_bytes;
2251a73374aSStanimir Varbanov 	u32 error;
22609c2845eSStanimir Varbanov 
22709c2845eSStanimir Varbanov 	error = pkt->error_type;
22809c2845eSStanimir Varbanov 	if (error != HFI_ERR_NONE)
2291a73374aSStanimir Varbanov 		goto done;
23009c2845eSStanimir Varbanov 
2311a73374aSStanimir Varbanov 	if (!pkt->num_properties) {
23209c2845eSStanimir Varbanov 		error = HFI_ERR_SYS_INVALID_PARAMETER;
2331a73374aSStanimir Varbanov 		goto done;
23409c2845eSStanimir Varbanov 	}
23509c2845eSStanimir Varbanov 
236a80d6771SGustavo A. R. Silva 	rem_bytes = pkt->hdr.size - sizeof(*pkt);
2371a73374aSStanimir Varbanov 	if (rem_bytes <= 0) {
23809c2845eSStanimir Varbanov 		/* missing property data */
23909c2845eSStanimir Varbanov 		error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
2401a73374aSStanimir Varbanov 		goto done;
24109c2845eSStanimir Varbanov 	}
24209c2845eSStanimir Varbanov 
2431a73374aSStanimir Varbanov 	error = hfi_parser(core, inst, pkt->data, rem_bytes);
24409c2845eSStanimir Varbanov 
2451a73374aSStanimir Varbanov done:
24609c2845eSStanimir Varbanov 	core->error = error;
24709c2845eSStanimir Varbanov 	complete(&core->done);
24809c2845eSStanimir Varbanov }
24909c2845eSStanimir Varbanov 
25009c2845eSStanimir Varbanov static void
sys_get_prop_image_version(struct venus_core * core,struct hfi_msg_sys_property_info_pkt * pkt)251ae8cdfc3SDikshita Agarwal sys_get_prop_image_version(struct venus_core *core,
25209c2845eSStanimir Varbanov 			   struct hfi_msg_sys_property_info_pkt *pkt)
25309c2845eSStanimir Varbanov {
254ae8cdfc3SDikshita Agarwal 	struct device *dev = core->dev;
255d566e78dSDikshita Agarwal 	u8 *smem_tbl_ptr;
256d566e78dSDikshita Agarwal 	u8 *img_ver;
25709c2845eSStanimir Varbanov 	int req_bytes;
258d566e78dSDikshita Agarwal 	size_t smem_blk_sz;
259ae8cdfc3SDikshita Agarwal 	int ret;
26009c2845eSStanimir Varbanov 
26109c2845eSStanimir Varbanov 	req_bytes = pkt->hdr.size - sizeof(*pkt);
26209c2845eSStanimir Varbanov 
2636f2f49aeSGustavo A. R. Silva 	if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1)
26409c2845eSStanimir Varbanov 		/* bad packet */
26509c2845eSStanimir Varbanov 		return;
26609c2845eSStanimir Varbanov 
2676f2f49aeSGustavo A. R. Silva 	img_ver = pkt->data;
268ae8cdfc3SDikshita Agarwal 	if (!img_ver)
269ae8cdfc3SDikshita Agarwal 		return;
270d566e78dSDikshita Agarwal 
271ae8cdfc3SDikshita Agarwal 	ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",
272ae8cdfc3SDikshita Agarwal 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
273ae8cdfc3SDikshita Agarwal 	if (ret)
274ae8cdfc3SDikshita Agarwal 		goto done;
275ae8cdfc3SDikshita Agarwal 
276ae8cdfc3SDikshita Agarwal 	ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",
277ae8cdfc3SDikshita Agarwal 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
278ae8cdfc3SDikshita Agarwal 	if (ret)
279ae8cdfc3SDikshita Agarwal 		goto done;
280ae8cdfc3SDikshita Agarwal 
281ae8cdfc3SDikshita Agarwal 	ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",
282ae8cdfc3SDikshita Agarwal 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
283ae8cdfc3SDikshita Agarwal 	if (ret)
284ae8cdfc3SDikshita Agarwal 		goto done;
285ae8cdfc3SDikshita Agarwal 
286ae8cdfc3SDikshita Agarwal 	dev_err(dev, VDBGL "error reading F/W version\n");
287ae8cdfc3SDikshita Agarwal 	return;
288ae8cdfc3SDikshita Agarwal 
289ae8cdfc3SDikshita Agarwal done:
290ae8cdfc3SDikshita Agarwal 	dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",
291ae8cdfc3SDikshita Agarwal 		img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);
292d566e78dSDikshita Agarwal 
293d566e78dSDikshita Agarwal 	smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
294d566e78dSDikshita Agarwal 		SMEM_IMG_VER_TBL, &smem_blk_sz);
295331e06bbSZhen Lei 	if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
296d566e78dSDikshita Agarwal 		memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
297d566e78dSDikshita Agarwal 		       img_ver, VER_STR_SZ);
29809c2845eSStanimir Varbanov }
29909c2845eSStanimir Varbanov 
hfi_sys_property_info(struct venus_core * core,struct venus_inst * inst,void * packet)30009c2845eSStanimir Varbanov static void hfi_sys_property_info(struct venus_core *core,
30109c2845eSStanimir Varbanov 				  struct venus_inst *inst, void *packet)
30209c2845eSStanimir Varbanov {
30309c2845eSStanimir Varbanov 	struct hfi_msg_sys_property_info_pkt *pkt = packet;
30409c2845eSStanimir Varbanov 	struct device *dev = core->dev;
30509c2845eSStanimir Varbanov 
30609c2845eSStanimir Varbanov 	if (!pkt->num_properties) {
3078c91dc08SStanimir Varbanov 		dev_dbg(dev, VDBGL "no properties\n");
30809c2845eSStanimir Varbanov 		return;
30909c2845eSStanimir Varbanov 	}
31009c2845eSStanimir Varbanov 
3116f2f49aeSGustavo A. R. Silva 	switch (pkt->property) {
31209c2845eSStanimir Varbanov 	case HFI_PROPERTY_SYS_IMAGE_VERSION:
313ae8cdfc3SDikshita Agarwal 		sys_get_prop_image_version(core, pkt);
31409c2845eSStanimir Varbanov 		break;
31509c2845eSStanimir Varbanov 	default:
3168c91dc08SStanimir Varbanov 		dev_dbg(dev, VDBGL "unknown property data\n");
31709c2845eSStanimir Varbanov 		break;
31809c2845eSStanimir Varbanov 	}
31909c2845eSStanimir Varbanov }
32009c2845eSStanimir Varbanov 
hfi_sys_rel_resource_done(struct venus_core * core,struct venus_inst * inst,void * packet)32109c2845eSStanimir Varbanov static void hfi_sys_rel_resource_done(struct venus_core *core,
32209c2845eSStanimir Varbanov 				      struct venus_inst *inst,
32309c2845eSStanimir Varbanov 				      void *packet)
32409c2845eSStanimir Varbanov {
32509c2845eSStanimir Varbanov 	struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
32609c2845eSStanimir Varbanov 
32709c2845eSStanimir Varbanov 	core->error = pkt->error_type;
32809c2845eSStanimir Varbanov 	complete(&core->done);
32909c2845eSStanimir Varbanov }
33009c2845eSStanimir Varbanov 
hfi_sys_ping_done(struct venus_core * core,struct venus_inst * inst,void * packet)33109c2845eSStanimir Varbanov static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
33209c2845eSStanimir Varbanov 			      void *packet)
33309c2845eSStanimir Varbanov {
33409c2845eSStanimir Varbanov 	struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
33509c2845eSStanimir Varbanov 
33609c2845eSStanimir Varbanov 	core->error = HFI_ERR_NONE;
33709c2845eSStanimir Varbanov 
33809c2845eSStanimir Varbanov 	if (pkt->client_data != 0xbeef)
33909c2845eSStanimir Varbanov 		core->error = HFI_ERR_SYS_FATAL;
34009c2845eSStanimir Varbanov 
34109c2845eSStanimir Varbanov 	complete(&core->done);
34209c2845eSStanimir Varbanov }
34309c2845eSStanimir Varbanov 
hfi_sys_idle_done(struct venus_core * core,struct venus_inst * inst,void * packet)34409c2845eSStanimir Varbanov static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
34509c2845eSStanimir Varbanov 			      void *packet)
34609c2845eSStanimir Varbanov {
3478c91dc08SStanimir Varbanov 	dev_dbg(core->dev, VDBGL "sys idle\n");
34809c2845eSStanimir Varbanov }
34909c2845eSStanimir Varbanov 
hfi_sys_pc_prepare_done(struct venus_core * core,struct venus_inst * inst,void * packet)35009c2845eSStanimir Varbanov static void hfi_sys_pc_prepare_done(struct venus_core *core,
35109c2845eSStanimir Varbanov 				    struct venus_inst *inst, void *packet)
35209c2845eSStanimir Varbanov {
35309c2845eSStanimir Varbanov 	struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
35409c2845eSStanimir Varbanov 
3558c91dc08SStanimir Varbanov 	dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n",
3568c91dc08SStanimir Varbanov 		pkt->error_type);
35709c2845eSStanimir Varbanov }
35809c2845eSStanimir Varbanov 
35909c2845eSStanimir Varbanov static unsigned int
session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_profile_level * profile_level)36009c2845eSStanimir Varbanov session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
36109c2845eSStanimir Varbanov 			       struct hfi_profile_level *profile_level)
36209c2845eSStanimir Varbanov {
36309c2845eSStanimir Varbanov 	struct hfi_profile_level *hfi;
36409c2845eSStanimir Varbanov 	u32 req_bytes;
36509c2845eSStanimir Varbanov 
36609c2845eSStanimir Varbanov 	req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
36709c2845eSStanimir Varbanov 
36809c2845eSStanimir Varbanov 	if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
36909c2845eSStanimir Varbanov 		/* bad packet */
37009c2845eSStanimir Varbanov 		return HFI_ERR_SESSION_INVALID_PARAMETER;
37109c2845eSStanimir Varbanov 
3726f2f49aeSGustavo A. R. Silva 	hfi = (struct hfi_profile_level *)&pkt->data[0];
37309c2845eSStanimir Varbanov 	profile_level->profile = hfi->profile;
37409c2845eSStanimir Varbanov 	profile_level->level = hfi->level;
37509c2845eSStanimir Varbanov 
37609c2845eSStanimir Varbanov 	return HFI_ERR_NONE;
37709c2845eSStanimir Varbanov }
37809c2845eSStanimir Varbanov 
37909c2845eSStanimir Varbanov static unsigned int
session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_buffer_requirements * bufreq)38009c2845eSStanimir Varbanov session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
38109c2845eSStanimir Varbanov 			 struct hfi_buffer_requirements *bufreq)
38209c2845eSStanimir Varbanov {
38309c2845eSStanimir Varbanov 	struct hfi_buffer_requirements *buf_req;
38409c2845eSStanimir Varbanov 	u32 req_bytes;
38509c2845eSStanimir Varbanov 	unsigned int idx = 0;
38609c2845eSStanimir Varbanov 
38709c2845eSStanimir Varbanov 	req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
38809c2845eSStanimir Varbanov 
3896f2f49aeSGustavo A. R. Silva 	if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0])
39009c2845eSStanimir Varbanov 		/* bad packet */
39109c2845eSStanimir Varbanov 		return HFI_ERR_SESSION_INVALID_PARAMETER;
39209c2845eSStanimir Varbanov 
3936f2f49aeSGustavo A. R. Silva 	buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];
39409c2845eSStanimir Varbanov 	if (!buf_req)
39509c2845eSStanimir Varbanov 		return HFI_ERR_SESSION_INVALID_PARAMETER;
39609c2845eSStanimir Varbanov 
39709c2845eSStanimir Varbanov 	while (req_bytes) {
39809c2845eSStanimir Varbanov 		memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
39909c2845eSStanimir Varbanov 		idx++;
40009c2845eSStanimir Varbanov 
401*db6bd472SVikash Garodia 		if (idx >= HFI_BUFFER_TYPE_MAX)
40209c2845eSStanimir Varbanov 			return HFI_ERR_SESSION_INVALID_PARAMETER;
40309c2845eSStanimir Varbanov 
40409c2845eSStanimir Varbanov 		req_bytes -= sizeof(struct hfi_buffer_requirements);
40509c2845eSStanimir Varbanov 		buf_req++;
40609c2845eSStanimir Varbanov 	}
40709c2845eSStanimir Varbanov 
40809c2845eSStanimir Varbanov 	return HFI_ERR_NONE;
40909c2845eSStanimir Varbanov }
41009c2845eSStanimir Varbanov 
hfi_session_prop_info(struct venus_core * core,struct venus_inst * inst,void * packet)41109c2845eSStanimir Varbanov static void hfi_session_prop_info(struct venus_core *core,
41209c2845eSStanimir Varbanov 				  struct venus_inst *inst, void *packet)
41309c2845eSStanimir Varbanov {
41409c2845eSStanimir Varbanov 	struct hfi_msg_session_property_info_pkt *pkt = packet;
41509c2845eSStanimir Varbanov 	struct device *dev = core->dev;
41609c2845eSStanimir Varbanov 	union hfi_get_property *hprop = &inst->hprop;
41709c2845eSStanimir Varbanov 	unsigned int error = HFI_ERR_NONE;
41809c2845eSStanimir Varbanov 
41909c2845eSStanimir Varbanov 	if (!pkt->num_properties) {
42009c2845eSStanimir Varbanov 		error = HFI_ERR_SESSION_INVALID_PARAMETER;
42109c2845eSStanimir Varbanov 		dev_err(dev, "%s: no properties\n", __func__);
42209c2845eSStanimir Varbanov 		goto done;
42309c2845eSStanimir Varbanov 	}
42409c2845eSStanimir Varbanov 
4256f2f49aeSGustavo A. R. Silva 	switch (pkt->property) {
42609c2845eSStanimir Varbanov 	case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
42709c2845eSStanimir Varbanov 		memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
42809c2845eSStanimir Varbanov 		error = session_get_prop_buf_req(pkt, hprop->bufreq);
42909c2845eSStanimir Varbanov 		break;
43009c2845eSStanimir Varbanov 	case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
43109c2845eSStanimir Varbanov 		memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
43209c2845eSStanimir Varbanov 		error = session_get_prop_profile_level(pkt,
43309c2845eSStanimir Varbanov 						       &hprop->profile_level);
43409c2845eSStanimir Varbanov 		break;
43509c2845eSStanimir Varbanov 	case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
43609c2845eSStanimir Varbanov 		break;
43709c2845eSStanimir Varbanov 	default:
4386f2f49aeSGustavo A. R. Silva 		dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property);
43909c2845eSStanimir Varbanov 		return;
44009c2845eSStanimir Varbanov 	}
44109c2845eSStanimir Varbanov 
44209c2845eSStanimir Varbanov done:
44309c2845eSStanimir Varbanov 	inst->error = error;
44409c2845eSStanimir Varbanov 	complete(&inst->done);
44509c2845eSStanimir Varbanov }
44609c2845eSStanimir Varbanov 
hfi_session_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)44709c2845eSStanimir Varbanov static void hfi_session_init_done(struct venus_core *core,
44809c2845eSStanimir Varbanov 				  struct venus_inst *inst, void *packet)
44909c2845eSStanimir Varbanov {
45009c2845eSStanimir Varbanov 	struct hfi_msg_session_init_done_pkt *pkt = packet;
4511a73374aSStanimir Varbanov 	int rem_bytes;
4521a73374aSStanimir Varbanov 	u32 error;
45309c2845eSStanimir Varbanov 
45409c2845eSStanimir Varbanov 	error = pkt->error_type;
45509c2845eSStanimir Varbanov 	if (error != HFI_ERR_NONE)
45609c2845eSStanimir Varbanov 		goto done;
45709c2845eSStanimir Varbanov 
4581a73374aSStanimir Varbanov 	if (!IS_V1(core))
45909c2845eSStanimir Varbanov 		goto done;
46009c2845eSStanimir Varbanov 
461a80d6771SGustavo A. R. Silva 	rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
4621a73374aSStanimir Varbanov 	if (rem_bytes <= 0) {
4631a73374aSStanimir Varbanov 		error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
4641a73374aSStanimir Varbanov 		goto done;
4651a73374aSStanimir Varbanov 	}
46609c2845eSStanimir Varbanov 
4671a73374aSStanimir Varbanov 	error = hfi_parser(core, inst, pkt->data, rem_bytes);
46809c2845eSStanimir Varbanov done:
46909c2845eSStanimir Varbanov 	inst->error = error;
47009c2845eSStanimir Varbanov 	complete(&inst->done);
47109c2845eSStanimir Varbanov }
47209c2845eSStanimir Varbanov 
hfi_session_load_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)47309c2845eSStanimir Varbanov static void hfi_session_load_res_done(struct venus_core *core,
47409c2845eSStanimir Varbanov 				      struct venus_inst *inst, void *packet)
47509c2845eSStanimir Varbanov {
47609c2845eSStanimir Varbanov 	struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
47709c2845eSStanimir Varbanov 
47809c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
47909c2845eSStanimir Varbanov 	complete(&inst->done);
48009c2845eSStanimir Varbanov }
48109c2845eSStanimir Varbanov 
hfi_session_flush_done(struct venus_core * core,struct venus_inst * inst,void * packet)48209c2845eSStanimir Varbanov static void hfi_session_flush_done(struct venus_core *core,
48309c2845eSStanimir Varbanov 				   struct venus_inst *inst, void *packet)
48409c2845eSStanimir Varbanov {
48509c2845eSStanimir Varbanov 	struct hfi_msg_session_flush_done_pkt *pkt = packet;
48609c2845eSStanimir Varbanov 
48709c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
48809c2845eSStanimir Varbanov 	complete(&inst->done);
48985872f86SStanimir Varbanov 	if (inst->ops->flush_done)
49085872f86SStanimir Varbanov 		inst->ops->flush_done(inst);
49109c2845eSStanimir Varbanov }
49209c2845eSStanimir Varbanov 
hfi_session_etb_done(struct venus_core * core,struct venus_inst * inst,void * packet)49309c2845eSStanimir Varbanov static void hfi_session_etb_done(struct venus_core *core,
49409c2845eSStanimir Varbanov 				 struct venus_inst *inst, void *packet)
49509c2845eSStanimir Varbanov {
49609c2845eSStanimir Varbanov 	struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
49709c2845eSStanimir Varbanov 
49809c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
49909c2845eSStanimir Varbanov 	inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
50009c2845eSStanimir Varbanov 			    pkt->filled_len, pkt->offset, 0, 0, 0);
50109c2845eSStanimir Varbanov }
50209c2845eSStanimir Varbanov 
hfi_session_ftb_done(struct venus_core * core,struct venus_inst * inst,void * packet)50309c2845eSStanimir Varbanov static void hfi_session_ftb_done(struct venus_core *core,
50409c2845eSStanimir Varbanov 				 struct venus_inst *inst, void *packet)
50509c2845eSStanimir Varbanov {
50609c2845eSStanimir Varbanov 	u32 session_type = inst->session_type;
50709c2845eSStanimir Varbanov 	u64 timestamp_us = 0;
50809c2845eSStanimir Varbanov 	u32 timestamp_hi = 0, timestamp_lo = 0;
50909c2845eSStanimir Varbanov 	unsigned int error;
51009c2845eSStanimir Varbanov 	u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
51109c2845eSStanimir Varbanov 	u32 pic_type = 0, buffer_type = 0, output_tag = -1;
51209c2845eSStanimir Varbanov 
51309c2845eSStanimir Varbanov 	if (session_type == VIDC_SESSION_TYPE_ENC) {
51409c2845eSStanimir Varbanov 		struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
51509c2845eSStanimir Varbanov 
51609c2845eSStanimir Varbanov 		timestamp_hi = pkt->time_stamp_hi;
51709c2845eSStanimir Varbanov 		timestamp_lo = pkt->time_stamp_lo;
51809c2845eSStanimir Varbanov 		hfi_flags = pkt->flags;
51909c2845eSStanimir Varbanov 		offset = pkt->offset;
52009c2845eSStanimir Varbanov 		filled_len = pkt->filled_len;
52109c2845eSStanimir Varbanov 		pic_type = pkt->picture_type;
52209c2845eSStanimir Varbanov 		output_tag = pkt->output_tag;
52309c2845eSStanimir Varbanov 		buffer_type = HFI_BUFFER_OUTPUT;
52409c2845eSStanimir Varbanov 
52509c2845eSStanimir Varbanov 		error = pkt->error_type;
52609c2845eSStanimir Varbanov 	} else if (session_type == VIDC_SESSION_TYPE_DEC) {
52709c2845eSStanimir Varbanov 		struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
52809c2845eSStanimir Varbanov 			packet;
52909c2845eSStanimir Varbanov 
53009c2845eSStanimir Varbanov 		timestamp_hi = pkt->time_stamp_hi;
53109c2845eSStanimir Varbanov 		timestamp_lo = pkt->time_stamp_lo;
53209c2845eSStanimir Varbanov 		hfi_flags = pkt->flags;
53309c2845eSStanimir Varbanov 		offset = pkt->offset;
53409c2845eSStanimir Varbanov 		filled_len = pkt->filled_len;
53509c2845eSStanimir Varbanov 		pic_type = pkt->picture_type;
53609c2845eSStanimir Varbanov 		output_tag = pkt->output_tag;
53709c2845eSStanimir Varbanov 
53809c2845eSStanimir Varbanov 		if (pkt->stream_id == 0)
53909c2845eSStanimir Varbanov 			buffer_type = HFI_BUFFER_OUTPUT;
54009c2845eSStanimir Varbanov 		else if (pkt->stream_id == 1)
54109c2845eSStanimir Varbanov 			buffer_type = HFI_BUFFER_OUTPUT2;
54209c2845eSStanimir Varbanov 
54309c2845eSStanimir Varbanov 		error = pkt->error_type;
54409c2845eSStanimir Varbanov 	} else {
54509c2845eSStanimir Varbanov 		error = HFI_ERR_SESSION_INVALID_PARAMETER;
54609c2845eSStanimir Varbanov 	}
54709c2845eSStanimir Varbanov 
5485f43f90aSStanimir Varbanov 	if (buffer_type != HFI_BUFFER_OUTPUT &&
5495f43f90aSStanimir Varbanov 	    buffer_type != HFI_BUFFER_OUTPUT2)
55009c2845eSStanimir Varbanov 		goto done;
55109c2845eSStanimir Varbanov 
55209c2845eSStanimir Varbanov 	if (hfi_flags & HFI_BUFFERFLAG_EOS)
55309c2845eSStanimir Varbanov 		flags |= V4L2_BUF_FLAG_LAST;
55409c2845eSStanimir Varbanov 
55509c2845eSStanimir Varbanov 	switch (pic_type) {
55609c2845eSStanimir Varbanov 	case HFI_PICTURE_IDR:
55709c2845eSStanimir Varbanov 	case HFI_PICTURE_I:
55809c2845eSStanimir Varbanov 		flags |= V4L2_BUF_FLAG_KEYFRAME;
55909c2845eSStanimir Varbanov 		break;
56009c2845eSStanimir Varbanov 	case HFI_PICTURE_P:
56109c2845eSStanimir Varbanov 		flags |= V4L2_BUF_FLAG_PFRAME;
56209c2845eSStanimir Varbanov 		break;
56309c2845eSStanimir Varbanov 	case HFI_PICTURE_B:
56409c2845eSStanimir Varbanov 		flags |= V4L2_BUF_FLAG_BFRAME;
56509c2845eSStanimir Varbanov 		break;
56609c2845eSStanimir Varbanov 	case HFI_FRAME_NOTCODED:
56709c2845eSStanimir Varbanov 	case HFI_UNUSED_PICT:
56809c2845eSStanimir Varbanov 	case HFI_FRAME_YUV:
56909c2845eSStanimir Varbanov 	default:
57009c2845eSStanimir Varbanov 		break;
57109c2845eSStanimir Varbanov 	}
57209c2845eSStanimir Varbanov 
57309c2845eSStanimir Varbanov 	if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
57409c2845eSStanimir Varbanov 		timestamp_us = timestamp_hi;
57509c2845eSStanimir Varbanov 		timestamp_us = (timestamp_us << 32) | timestamp_lo;
57609c2845eSStanimir Varbanov 	}
57709c2845eSStanimir Varbanov 
57809c2845eSStanimir Varbanov done:
57909c2845eSStanimir Varbanov 	inst->error = error;
58009c2845eSStanimir Varbanov 	inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
58109c2845eSStanimir Varbanov 			    offset, flags, hfi_flags, timestamp_us);
58209c2845eSStanimir Varbanov }
58309c2845eSStanimir Varbanov 
hfi_session_start_done(struct venus_core * core,struct venus_inst * inst,void * packet)58409c2845eSStanimir Varbanov static void hfi_session_start_done(struct venus_core *core,
58509c2845eSStanimir Varbanov 				   struct venus_inst *inst, void *packet)
58609c2845eSStanimir Varbanov {
58709c2845eSStanimir Varbanov 	struct hfi_msg_session_start_done_pkt *pkt = packet;
58809c2845eSStanimir Varbanov 
58909c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
59009c2845eSStanimir Varbanov 	complete(&inst->done);
59109c2845eSStanimir Varbanov }
59209c2845eSStanimir Varbanov 
hfi_session_stop_done(struct venus_core * core,struct venus_inst * inst,void * packet)59309c2845eSStanimir Varbanov static void hfi_session_stop_done(struct venus_core *core,
59409c2845eSStanimir Varbanov 				  struct venus_inst *inst, void *packet)
59509c2845eSStanimir Varbanov {
59609c2845eSStanimir Varbanov 	struct hfi_msg_session_stop_done_pkt *pkt = packet;
59709c2845eSStanimir Varbanov 
59809c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
59909c2845eSStanimir Varbanov 	complete(&inst->done);
60009c2845eSStanimir Varbanov }
60109c2845eSStanimir Varbanov 
hfi_session_rel_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)60209c2845eSStanimir Varbanov static void hfi_session_rel_res_done(struct venus_core *core,
60309c2845eSStanimir Varbanov 				     struct venus_inst *inst, void *packet)
60409c2845eSStanimir Varbanov {
60509c2845eSStanimir Varbanov 	struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
60609c2845eSStanimir Varbanov 
60709c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
60809c2845eSStanimir Varbanov 	complete(&inst->done);
60909c2845eSStanimir Varbanov }
61009c2845eSStanimir Varbanov 
hfi_session_rel_buf_done(struct venus_core * core,struct venus_inst * inst,void * packet)61109c2845eSStanimir Varbanov static void hfi_session_rel_buf_done(struct venus_core *core,
61209c2845eSStanimir Varbanov 				     struct venus_inst *inst, void *packet)
61309c2845eSStanimir Varbanov {
61409c2845eSStanimir Varbanov 	struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
61509c2845eSStanimir Varbanov 
61609c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
61709c2845eSStanimir Varbanov 	complete(&inst->done);
61809c2845eSStanimir Varbanov }
61909c2845eSStanimir Varbanov 
hfi_session_end_done(struct venus_core * core,struct venus_inst * inst,void * packet)62009c2845eSStanimir Varbanov static void hfi_session_end_done(struct venus_core *core,
62109c2845eSStanimir Varbanov 				 struct venus_inst *inst, void *packet)
62209c2845eSStanimir Varbanov {
62309c2845eSStanimir Varbanov 	struct hfi_msg_session_end_done_pkt *pkt = packet;
62409c2845eSStanimir Varbanov 
62509c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
62609c2845eSStanimir Varbanov 	complete(&inst->done);
62709c2845eSStanimir Varbanov }
62809c2845eSStanimir Varbanov 
hfi_session_abort_done(struct venus_core * core,struct venus_inst * inst,void * packet)62909c2845eSStanimir Varbanov static void hfi_session_abort_done(struct venus_core *core,
63009c2845eSStanimir Varbanov 				   struct venus_inst *inst, void *packet)
63109c2845eSStanimir Varbanov {
63209c2845eSStanimir Varbanov 	struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
63309c2845eSStanimir Varbanov 
63409c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
63509c2845eSStanimir Varbanov 	complete(&inst->done);
63609c2845eSStanimir Varbanov }
63709c2845eSStanimir Varbanov 
hfi_session_get_seq_hdr_done(struct venus_core * core,struct venus_inst * inst,void * packet)63809c2845eSStanimir Varbanov static void hfi_session_get_seq_hdr_done(struct venus_core *core,
63909c2845eSStanimir Varbanov 					 struct venus_inst *inst, void *packet)
64009c2845eSStanimir Varbanov {
64109c2845eSStanimir Varbanov 	struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
64209c2845eSStanimir Varbanov 
64309c2845eSStanimir Varbanov 	inst->error = pkt->error_type;
64409c2845eSStanimir Varbanov 	complete(&inst->done);
64509c2845eSStanimir Varbanov }
64609c2845eSStanimir Varbanov 
64709c2845eSStanimir Varbanov struct hfi_done_handler {
64809c2845eSStanimir Varbanov 	u32 pkt;
64909c2845eSStanimir Varbanov 	u32 pkt_sz;
65009c2845eSStanimir Varbanov 	u32 pkt_sz2;
65109c2845eSStanimir Varbanov 	void (*done)(struct venus_core *, struct venus_inst *, void *);
65209c2845eSStanimir Varbanov 	bool is_sys_pkt;
65309c2845eSStanimir Varbanov };
65409c2845eSStanimir Varbanov 
65509c2845eSStanimir Varbanov static const struct hfi_done_handler handlers[] = {
65609c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_EVENT_NOTIFY,
65709c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
65809c2845eSStanimir Varbanov 	 .done = hfi_event_notify,
65909c2845eSStanimir Varbanov 	},
66009c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_INIT,
66109c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
66209c2845eSStanimir Varbanov 	 .done = hfi_sys_init_done,
66309c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
66409c2845eSStanimir Varbanov 	},
66509c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_PROPERTY_INFO,
66609c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
66709c2845eSStanimir Varbanov 	 .done = hfi_sys_property_info,
66809c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
66909c2845eSStanimir Varbanov 	},
67009c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
67109c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
67209c2845eSStanimir Varbanov 	 .done = hfi_sys_rel_resource_done,
67309c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
67409c2845eSStanimir Varbanov 	},
67509c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_PING_ACK,
67609c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
67709c2845eSStanimir Varbanov 	 .done = hfi_sys_ping_done,
67809c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
67909c2845eSStanimir Varbanov 	},
68009c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_IDLE,
68109c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
68209c2845eSStanimir Varbanov 	 .done = hfi_sys_idle_done,
68309c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
68409c2845eSStanimir Varbanov 	},
68509c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_PC_PREP,
68609c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
68709c2845eSStanimir Varbanov 	 .done = hfi_sys_pc_prepare_done,
68809c2845eSStanimir Varbanov 	 .is_sys_pkt = true,
68909c2845eSStanimir Varbanov 	},
69009c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_SESSION_INIT,
69109c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
69209c2845eSStanimir Varbanov 	 .done = hfi_session_init_done,
69309c2845eSStanimir Varbanov 	},
69409c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_SESSION_END,
69509c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
69609c2845eSStanimir Varbanov 	 .done = hfi_session_end_done,
69709c2845eSStanimir Varbanov 	},
69809c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
69909c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
70009c2845eSStanimir Varbanov 	 .done = hfi_session_load_res_done,
70109c2845eSStanimir Varbanov 	},
70209c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_START,
70309c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
70409c2845eSStanimir Varbanov 	 .done = hfi_session_start_done,
70509c2845eSStanimir Varbanov 	},
70609c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_STOP,
70709c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
70809c2845eSStanimir Varbanov 	 .done = hfi_session_stop_done,
70909c2845eSStanimir Varbanov 	},
71009c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SYS_SESSION_ABORT,
71109c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
71209c2845eSStanimir Varbanov 	 .done = hfi_session_abort_done,
71309c2845eSStanimir Varbanov 	},
71409c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
71509c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
71609c2845eSStanimir Varbanov 	 .done = hfi_session_etb_done,
71709c2845eSStanimir Varbanov 	},
71809c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_FILL_BUFFER,
71909c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
72009c2845eSStanimir Varbanov 	 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
72109c2845eSStanimir Varbanov 	 .done = hfi_session_ftb_done,
72209c2845eSStanimir Varbanov 	},
72309c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_FLUSH,
72409c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
72509c2845eSStanimir Varbanov 	 .done = hfi_session_flush_done,
72609c2845eSStanimir Varbanov 	},
72709c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
72809c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
72909c2845eSStanimir Varbanov 	 .done = hfi_session_prop_info,
73009c2845eSStanimir Varbanov 	},
73109c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
73209c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
73309c2845eSStanimir Varbanov 	 .done = hfi_session_rel_res_done,
73409c2845eSStanimir Varbanov 	},
73509c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
73609c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
73709c2845eSStanimir Varbanov 	 .done = hfi_session_get_seq_hdr_done,
73809c2845eSStanimir Varbanov 	},
73909c2845eSStanimir Varbanov 	{.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
74009c2845eSStanimir Varbanov 	 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
74109c2845eSStanimir Varbanov 	 .done = hfi_session_rel_buf_done,
74209c2845eSStanimir Varbanov 	},
74309c2845eSStanimir Varbanov };
74409c2845eSStanimir Varbanov 
hfi_process_watchdog_timeout(struct venus_core * core)74509c2845eSStanimir Varbanov void hfi_process_watchdog_timeout(struct venus_core *core)
74609c2845eSStanimir Varbanov {
74709c2845eSStanimir Varbanov 	event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
74809c2845eSStanimir Varbanov }
74909c2845eSStanimir Varbanov 
to_instance(struct venus_core * core,u32 session_id)75009c2845eSStanimir Varbanov static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
75109c2845eSStanimir Varbanov {
75209c2845eSStanimir Varbanov 	struct venus_inst *inst;
75309c2845eSStanimir Varbanov 
75409c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
75509c2845eSStanimir Varbanov 	list_for_each_entry(inst, &core->instances, list)
75609c2845eSStanimir Varbanov 		if (hash32_ptr(inst) == session_id) {
75709c2845eSStanimir Varbanov 			mutex_unlock(&core->lock);
75809c2845eSStanimir Varbanov 			return inst;
75909c2845eSStanimir Varbanov 		}
76009c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
76109c2845eSStanimir Varbanov 
76209c2845eSStanimir Varbanov 	return NULL;
76309c2845eSStanimir Varbanov }
76409c2845eSStanimir Varbanov 
hfi_process_msg_packet(struct venus_core * core,struct hfi_pkt_hdr * hdr)76509c2845eSStanimir Varbanov u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
76609c2845eSStanimir Varbanov {
76709c2845eSStanimir Varbanov 	const struct hfi_done_handler *handler;
76809c2845eSStanimir Varbanov 	struct device *dev = core->dev;
76909c2845eSStanimir Varbanov 	struct venus_inst *inst;
77009c2845eSStanimir Varbanov 	bool found = false;
77109c2845eSStanimir Varbanov 	unsigned int i;
77209c2845eSStanimir Varbanov 
77309c2845eSStanimir Varbanov 	for (i = 0; i < ARRAY_SIZE(handlers); i++) {
77409c2845eSStanimir Varbanov 		handler = &handlers[i];
77509c2845eSStanimir Varbanov 		if (handler->pkt != hdr->pkt_type)
77609c2845eSStanimir Varbanov 			continue;
77709c2845eSStanimir Varbanov 		found = true;
77809c2845eSStanimir Varbanov 		break;
77909c2845eSStanimir Varbanov 	}
78009c2845eSStanimir Varbanov 
78109c2845eSStanimir Varbanov 	if (!found)
78209c2845eSStanimir Varbanov 		return hdr->pkt_type;
78309c2845eSStanimir Varbanov 
78409c2845eSStanimir Varbanov 	if (hdr->size && hdr->size < handler->pkt_sz &&
78509c2845eSStanimir Varbanov 	    hdr->size < handler->pkt_sz2) {
78609c2845eSStanimir Varbanov 		dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
78709c2845eSStanimir Varbanov 			hdr->size, handler->pkt_sz, hdr->pkt_type);
78809c2845eSStanimir Varbanov 
78909c2845eSStanimir Varbanov 		return hdr->pkt_type;
79009c2845eSStanimir Varbanov 	}
79109c2845eSStanimir Varbanov 
79209c2845eSStanimir Varbanov 	if (handler->is_sys_pkt) {
79309c2845eSStanimir Varbanov 		inst = NULL;
79409c2845eSStanimir Varbanov 	} else {
79509c2845eSStanimir Varbanov 		struct hfi_session_pkt *pkt;
79609c2845eSStanimir Varbanov 
79709c2845eSStanimir Varbanov 		pkt = (struct hfi_session_pkt *)hdr;
79809c2845eSStanimir Varbanov 		inst = to_instance(core, pkt->shdr.session_id);
79909c2845eSStanimir Varbanov 
80009c2845eSStanimir Varbanov 		if (!inst)
80109c2845eSStanimir Varbanov 			dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
80209c2845eSStanimir Varbanov 				 pkt->shdr.session_id,
80309c2845eSStanimir Varbanov 				 handler ? handler->pkt : 0);
80409c2845eSStanimir Varbanov 
80509c2845eSStanimir Varbanov 		/*
80609c2845eSStanimir Varbanov 		 * Event of type HFI_EVENT_SYS_ERROR will not have any session
80709c2845eSStanimir Varbanov 		 * associated with it
80809c2845eSStanimir Varbanov 		 */
80909c2845eSStanimir Varbanov 		if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
81009c2845eSStanimir Varbanov 			dev_err(dev, "got invalid session id:%x\n",
81109c2845eSStanimir Varbanov 				pkt->shdr.session_id);
81209c2845eSStanimir Varbanov 			goto invalid_session;
81309c2845eSStanimir Varbanov 		}
81409c2845eSStanimir Varbanov 	}
81509c2845eSStanimir Varbanov 
81609c2845eSStanimir Varbanov 	handler->done(core, inst, hdr);
81709c2845eSStanimir Varbanov 
81809c2845eSStanimir Varbanov invalid_session:
81909c2845eSStanimir Varbanov 	return hdr->pkt_type;
82009c2845eSStanimir Varbanov }
821