Forráskód Böngészése

driver: video: handle input port settings change

add support for input port settings change raised
by fw. update driver subscribed port settings
properties with instance. Raise event to client.
Release, get, create and queue input internal buffers.
Send resume commond to fw on input port.
Add support to destroy internal buffers.

Change-Id: Ic979cf2d0c7298b8083347173a973d553ed52af8
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 4 éve
szülő
commit
3858225faf

+ 4 - 0
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -905,6 +905,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
 		V4L2_CID_MPEG_VIDEO_MUTE_YUV,
 		HFI_PROP_CONCEAL_COLOR_10BIT},
+
+	{STAGE, DEC|ENC, CODECS_ALL, 1, 2, 1, 2},
+	{PIPE, DEC|ENC, CODECS_ALL, 1, 4, 1, 4},
+	{POC, DEC, H264, 0, 1, 1, 0},
 };
 
 /*

+ 2 - 0
driver/vidc/inc/msm_vdec.h

@@ -18,5 +18,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
 int msm_vdec_inst_init(struct msm_vidc_inst *inst);
+int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);
+int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
 
 #endif // _MSM_VDEC_H_

+ 2 - 0
driver/vidc/inc/msm_vidc_driver.h

@@ -132,6 +132,8 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
 int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *buf);
 int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
+int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buffer);
 struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *vbuf);
 struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,

+ 4 - 2
driver/vidc/inc/msm_vidc_inst.h

@@ -111,8 +111,7 @@ struct msm_vidc_inst {
 	bool                               subscribed_output_psc;
 	bool                               subscribed_input_prop;
 	bool                               subscribed_output_prop;
-	struct msm_vidc_subscription_params       vidc_subcr[MAX_PORT];
-	struct msm_vidc_subscription_params       hfi_subcr[MAX_PORT];
+	struct msm_vidc_subscription_params       subcr_params[MAX_PORT];
 	struct msm_vidc_decode_batch       decode_batch;
 	struct msm_vidc_decode_vpp_delay   decode_vpp_delay;
 	struct msm_vidc_session_idle       session_idle;
@@ -124,6 +123,9 @@ struct msm_vidc_inst {
 	struct msm_vidc_debug              debug;
 	struct msm_vidc_inst_capability   *capabilities;
 	struct completion                  completions[MAX_SIGNAL];
+	u32                                hfi_cmd_type;
+	u32                                hfi_port;
+
 };
 
 #endif // _MSM_VIDC_INST_H_

+ 10 - 6
driver/vidc/inc/msm_vidc_internal.h

@@ -323,6 +323,9 @@ enum msm_vidc_inst_capability_type {
 	DISPLAY_DELAY,
 	CONCEAL_COLOR_8BIT,
 	CONCEAL_COLOR_10BIT,
+	STAGE,
+	PIPE,
+	POC,
 	INST_CAP_MAX,
 };
 
@@ -539,16 +542,17 @@ struct msm_vidc_properties {
 };
 
 struct msm_vidc_subscription_params {
-	u32                    align_width;
-	u32                    align_height;
-	struct msm_vidc_crop   crop;
-	struct msm_vidc_color_info   color_info;
+	u32                    bitstream_resolution;
+	u64                    crop_offsets;
 	u32                    bit_depth;
 	u32                    cabac;
-	u32                    interlace;
-	u32                    min_count;
+	u32                    coded_frames;
+	u32                    fw_min_count;
 	u32                    pic_order_cnt;
+	u32                    color_info;
 	u32                    profile;
+	u32                    level;
+	u32                    tier;
 };
 
 struct msm_vidc_decode_vpp_delay {

+ 163 - 21
driver/vidc/src/msm_vdec.c

@@ -82,6 +82,7 @@ static int msm_vdec_set_bitstream_resolution(struct msm_vidc_inst *inst,
 	s_vpr_h(inst->sid, "%s: width: %d height: %d\n", __func__,
 			inst->fmts[INPUT_PORT].fmt.pix_mp.width,
 			inst->fmts[INPUT_PORT].fmt.pix_mp.height);
+	inst->subcr_params[port].bitstream_resolution = resolution;
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_BITSTREAM_RESOLUTION,
 			HFI_HOST_FLAGS_NONE,
@@ -135,7 +136,7 @@ static int msm_vdec_set_crop_offsets(struct msm_vidc_inst *inst,
 {
 	int rc = 0;
 	u32 left_offset, top_offset, right_offset, bottom_offset;
-	u32 payload[2];
+	u64 payload;
 
 	if (inst->fmts[INPUT_PORT].fmt.pix_mp.width <
 		inst->crop.width)
@@ -152,16 +153,17 @@ static int msm_vdec_set_crop_offsets(struct msm_vidc_inst *inst,
 	bottom_offset = (inst->fmts[INPUT_PORT].fmt.pix_mp.height -
 		inst->crop.height);
 
-	payload[0] = right_offset << 16 | bottom_offset;
-	payload[1] = left_offset << 16 | top_offset;
+	payload = (u64)right_offset << 48 | (u64)bottom_offset << 32 |
+		(u64)left_offset << 16 | top_offset;
 	s_vpr_h(inst->sid, "%s: left_offset: %d top_offset: %d "
 		"right_offset: %d bottom_offset: %d", __func__,
 		left_offset, top_offset, right_offset, bottom_offset);
+	inst->subcr_params[port].crop_offsets = payload;
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_CROP_OFFSETS,
 			HFI_HOST_FLAGS_NONE,
 			get_hfi_port(inst, port),
-			HFI_PAYLOAD_U64,
+			HFI_PAYLOAD_64_PACKED,
 			&payload,
 			sizeof(u64));
 	if (rc)
@@ -186,6 +188,8 @@ static int msm_vdec_set_bit_depth(struct msm_vidc_inst *inst,
 	if (colorformat == V4L2_PIX_FMT_VIDC_P010 ||
 	    colorformat == V4L2_PIX_FMT_VIDC_TP10C)
 		bitdepth = 10 << 16 | 10;
+
+	inst->subcr_params[port].bit_depth = bitdepth;
 	s_vpr_h(inst->sid, "%s: bit depth: %d", __func__, bitdepth);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
@@ -214,6 +218,8 @@ static int msm_vdec_set_cabac(struct msm_vidc_inst *inst,
 	rc = msm_vidc_v4l2_menu_to_hfi(inst, ENTROPY_MODE, &cabac);
 	if (rc)
 		return rc;
+
+	inst->subcr_params[port].cabac = cabac;
 	s_vpr_h(inst->sid, "%s: entropy mode: %d", __func__, cabac);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_CABAC_SESSION,
@@ -241,6 +247,7 @@ static int msm_vdec_set_coded_frames(struct msm_vidc_inst *inst,
 
 	/* (mb_adaptive_frame_field_flag << 1) | frame_mbs_only_flag */
 	coded_frames = 0;
+	inst->subcr_params[port].coded_frames = coded_frames;
 	s_vpr_h(inst->sid, "%s: coded frames: %d", __func__, coded_frames);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_CODED_FRAMES,
@@ -267,6 +274,7 @@ static int msm_vdec_set_min_output_count(struct msm_vidc_inst *inst,
 	}
 
 	min_output = inst->buffers.output.min_count;
+	inst->subcr_params[port].fw_min_count = min_output;
 	s_vpr_h(inst->sid, "%s: firmware min output count: %d",
 		__func__, min_output);
 	rc = venus_hfi_session_property(inst,
@@ -293,6 +301,7 @@ static int msm_vdec_set_picture_order_count(struct msm_vidc_inst *inst,
 		return -EINVAL;
 	}
 
+	inst->subcr_params[port].pic_order_cnt = poc;
 	s_vpr_h(inst->sid, "%s: picture order count: %d", __func__, poc);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_PIC_ORDER_CNT_TYPE,
@@ -311,7 +320,7 @@ static int msm_vdec_set_colorspace(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
 	int rc = 0;
-	u32 colorspace;
+	u32 colorspace, xfer_func, ycbcr_enc, color_info;
 
 	if (port != INPUT_PORT && port != OUTPUT_PORT) {
 		s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
@@ -319,13 +328,19 @@ static int msm_vdec_set_colorspace(struct msm_vidc_inst *inst,
 	}
 
 	colorspace = inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace;
-	s_vpr_h(inst->sid, "%s: colorspace: %d", __func__, colorspace);
+	xfer_func = inst->fmts[OUTPUT_PORT].fmt.pix_mp.xfer_func;
+	ycbcr_enc = inst->fmts[OUTPUT_PORT].fmt.pix_mp.ycbcr_enc;
+
+	color_info = ((ycbcr_enc << 16) & 0xFF0000) |
+		((xfer_func << 8) & 0xFF00) | (colorspace & 0xFF);
+	inst->subcr_params[port].color_info = color_info;
+	s_vpr_h(inst->sid, "%s: color info: %d", __func__, color_info);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_SIGNAL_COLOR_INFO,
 			HFI_HOST_FLAGS_NONE,
 			get_hfi_port(inst, port),
 			HFI_PAYLOAD_U32,
-			&colorspace,
+			&color_info,
 			sizeof(u32));
 	if (rc)
 		s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
@@ -345,6 +360,7 @@ static int msm_vdec_set_profile(struct msm_vidc_inst *inst,
 	}
 
 	profile = inst->capabilities->cap[PROFILE].value;
+	inst->subcr_params[port].profile = profile;
 	s_vpr_h(inst->sid, "%s: profile: %d", __func__, profile);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_PROFILE,
@@ -371,6 +387,7 @@ static int msm_vdec_set_level(struct msm_vidc_inst *inst,
 	}
 
 	level = inst->capabilities->cap[LEVEL].value;
+	inst->subcr_params[port].level = level;
 	s_vpr_h(inst->sid, "%s: level: %d", __func__, level);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_LEVEL,
@@ -397,6 +414,7 @@ static int msm_vdec_set_tier(struct msm_vidc_inst *inst,
 	}
 
 	tier = inst->capabilities->cap[HEVC_TIER].value;
+	inst->subcr_params[port].tier = tier;
 	s_vpr_h(inst->sid, "%s: tier: %d", __func__, tier);
 	rc = venus_hfi_session_property(inst,
 			HFI_PROP_TIER,
@@ -818,7 +836,7 @@ static int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
-/*
+
 static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
@@ -829,21 +847,26 @@ static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_SCRATCH);
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_BIN);
+	if (rc)
+		return rc;
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_COMV);
 	if (rc)
 		return rc;
-	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_SCRATCH_1);
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
 	if (rc)
 		return rc;
-	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_PERSIST_1);
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_LINE);
+	if (rc)
+		return rc;
+	rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
 	if (rc)
 		return rc;
 
 	return 0;
 }
-*/
 
-static int msm_vdec_port_settings_subscription(struct msm_vidc_inst *inst,
+static int msm_vdec_subscribe_port_settings_change(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
 	int rc = 0;
@@ -918,7 +941,7 @@ static int msm_vdec_port_settings_subscription(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-static int msm_vdec_property_subscription(struct msm_vidc_inst *inst,
+static int msm_vdec_subscribe_property(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
 	int rc = 0;
@@ -948,7 +971,7 @@ static int msm_vdec_property_subscription(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-static int msm_vdec_metadata_subscription(struct msm_vidc_inst *inst,
+static int msm_vdec_subscribe_metadata(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
 	int rc = 0;
@@ -978,7 +1001,7 @@ static int msm_vdec_metadata_subscription(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-static int msm_vdec_metadata_delivery(struct msm_vidc_inst *inst,
+static int msm_vdec_set_delivery_mode_metadata(struct msm_vidc_inst *inst,
 	enum msm_vidc_port_type port)
 {
 	int rc = 0;
@@ -1008,6 +1031,125 @@ static int msm_vdec_metadata_delivery(struct msm_vidc_inst *inst,
 	return rc;
 }
 
+static int msm_vdec_session_resume(struct msm_vidc_inst *inst,
+	enum msm_vidc_port_type port)
+{
+	int rc = 0;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	d_vpr_h("%s()\n", __func__);
+
+	rc = venus_hfi_session_command(inst,
+			HFI_CMD_RESUME,
+			port,
+			HFI_PAYLOAD_NONE,
+			NULL,
+			0);
+
+	return rc;
+}
+
+static msm_vdec_update_input_properties(struct msm_vidc_inst *inst)
+{
+	struct msm_vidc_subscription_params subsc_params;
+	u32 width, height;
+
+	subsc_params = inst->subcr_params[INPUT_PORT];
+	width = (subsc_params.bitstream_resolution &
+		HFI_BITMASK_BITSTREAM_WIDTH) >> 16;
+	height = subsc_params.bitstream_resolution &
+		HFI_BITMASK_BITSTREAM_HEIGHT;
+
+	inst->fmts[INPUT_PORT].fmt.pix_mp.width = width;
+	inst->fmts[INPUT_PORT].fmt.pix_mp.height = height;
+
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.width = VENUS_Y_STRIDE(
+		v4l2_colorformat_to_media(
+		inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__),
+		width);
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.height = VENUS_Y_SCANLINES(
+		v4l2_colorformat_to_media(
+		inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat,	__func__),
+		height);
+	//inst->fmts[OUTPUT_PORT].fmt.pix_mp.bytesperline =
+		//inst->fmts[OUTPUT_PORT].fmt.pix_mp.width;
+
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace =
+		(subsc_params.color_info & 0xFF0000) >> 16;
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.xfer_func =
+		(subsc_params.color_info & 0xFF00) >> 8;
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.ycbcr_enc =
+		subsc_params.color_info & 0xFF;
+
+	inst->buffers.output.min_count = subsc_params.fw_min_count;
+
+	inst->crop.top = subsc_params.crop_offsets & 0xFFFF;
+	inst->crop.left = (subsc_params.crop_offsets >> 16) & 0xFFFF;
+	inst->crop.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height -
+		((subsc_params.crop_offsets >> 32) & 0xFFFF);
+	inst->crop.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width -
+		((subsc_params.crop_offsets >> 48) & 0xFFFF);
+
+	inst->capabilities->cap[PROFILE].value = subsc_params.profile;
+	inst->capabilities->cap[LEVEL].value = subsc_params.level;
+	inst->capabilities->cap[HEVC_TIER].value = subsc_params.tier;
+	inst->capabilities->cap[ENTROPY_MODE].value = subsc_params.cabac;
+	inst->capabilities->cap[POC].value = subsc_params.pic_order_cnt;
+
+	return 0;
+}
+
+int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
+{
+	u32 rc = 0;
+	struct v4l2_event event = {0};
+
+	if (!inst->vb2q[INPUT_PORT].streaming) {
+		s_vpr_e(inst->sid, "%s: input port not streaming\n",
+			__func__);
+		return 0;
+	}
+
+	rc = msm_vdec_update_input_properties(inst);
+	if (rc)
+		return rc;
+
+	event.type = V4L2_EVENT_SRC_CH_RESOLUTION;//todo
+	event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
+	v4l2_event_queue_fh(&inst->event_handler, &event);
+
+	rc = msm_vdec_release_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_get_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_create_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_queue_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_session_resume(inst, INPUT_PORT);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
+{
+	//todo
+	return 0;
+}
+
 int msm_vdec_stop_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
@@ -1070,15 +1212,15 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vdec_port_settings_subscription(inst, INPUT_PORT);
+	rc = msm_vdec_subscribe_port_settings_change(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
-	rc = msm_vdec_property_subscription(inst, INPUT_PORT);
+	rc = msm_vdec_subscribe_property(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
-	rc = msm_vdec_metadata_delivery(inst, INPUT_PORT);
+	rc = msm_vdec_set_delivery_mode_metadata(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
@@ -1125,11 +1267,11 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vdec_port_settings_subscription(inst, OUTPUT_PORT);
+	rc = msm_vdec_subscribe_port_settings_change(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
 
-	rc = msm_vdec_metadata_subscription(inst, OUTPUT_PORT);
+	rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
 

+ 2 - 0
driver/vidc/src/msm_vidc.c

@@ -789,6 +789,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	inst->domain = session_type;
 	inst->state = MSM_VIDC_OPEN;
 	inst->request = false;
+	inst->hfi_cmd_type = 0;
+	inst->hfi_port = 0;
 	for (i = 0; i < MAX_SIGNAL; i++)
 		init_completion(&inst->completions[i]);
 

+ 141 - 59
driver/vidc/src/msm_vidc_driver.c

@@ -34,14 +34,14 @@ void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
 	mbuf = get_meta_buffer(inst, vbuf);
 	if (!mbuf)
 		dprintk(tag, inst->sid,
-			"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x\n",
+			"%s: %s: idx %2d fd %3d off %d daddr %#llx size %d filled %d flags %#x ts %lld attr %#x\n",
 			str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
 			vbuf->index, vbuf->fd, vbuf->data_offset,
 			vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
 			vbuf->flags, vbuf->timestamp, vbuf->attr);
 	else
 		dprintk(tag, inst->sid,
-			"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x meta: fd %3d daddr %#x size %d\n",
+			"%s: %s: idx %2d fd %3d off %d daddr %#llx size %d filled %d flags %#x ts %lld attr %#x meta: fd %3d daddr %#llx size %d\n",
 			str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
 			vbuf->index, vbuf->fd, vbuf->data_offset,
 			vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
@@ -784,14 +784,78 @@ int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
 	return rc;
 }
 
-int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
-		enum msm_vidc_buffer_type buffer_type)
+int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buffer)
+{
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_allocations *allocations;
+	struct msm_vidc_mappings *mappings;
+	struct msm_vidc_alloc *alloc, *alloc_dummy;
+	struct msm_vidc_map  *map, *map_dummy;
+	struct msm_vidc_buffer *buf, *dummy;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!is_internal_buffer(buffer->type)) {
+		s_vpr_e(inst->sid, "%s: buffer type %#x is not internal\n",
+			__func__, buffer->type);
+		return 0;
+	}
+
+	s_vpr_h(inst->sid,
+		"%s: destroy buffer_type %#x, size %d device_addr %#x\n",
+		__func__, buffer->type, buffer->buffer_size,
+		buffer->device_addr);
+
+	buffers = msm_vidc_get_buffers(inst, buffer->type, __func__);
+	if (!buffers)
+		return -EINVAL;
+	allocations = msm_vidc_get_allocations(inst, buffer->type, __func__);
+	if (!allocations)
+		return -EINVAL;
+	mappings = msm_vidc_get_mappings(inst, buffer->type, __func__);
+	if (!mappings)
+		return -EINVAL;
+
+	list_for_each_entry_safe(map, map_dummy, &mappings->list, list) {
+		if (map->dmabuf == buffer->dmabuf) {
+			msm_vidc_memory_unmap(inst->core, map);
+			list_del(&map->list);
+			kfree(map);
+		}
+	}
+
+	list_for_each_entry_safe(alloc, alloc_dummy, &allocations->list, list) {
+		if (alloc->dmabuf == buffer->dmabuf) {
+			msm_vidc_memory_free(inst->core, alloc);
+			list_del(&alloc->list);
+			kfree(alloc);
+		}
+	}
+
+	list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
+		if (buf->dmabuf == buffer->dmabuf) {
+			list_del(&buf->list);
+			kfree(buf);
+		}
+	}
+
+	return 0;
+}
+
+int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
+	enum msm_vidc_buffer_type buffer_type, u32 index)
 {
 	int rc = 0;
 	struct msm_vidc_buffers *buffers;
 	struct msm_vidc_allocations *allocations;
 	struct msm_vidc_mappings *mappings;
-	int i;
+	struct msm_vidc_buffer *buffer;
+	struct msm_vidc_alloc *alloc;
+	struct msm_vidc_map *map;
 
 	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
@@ -814,67 +878,85 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 	if (!mappings)
 		return -EINVAL;
 
-	for (i = 0; i < buffers->min_count; i++) {
-		struct msm_vidc_buffer *buffer;
-		struct msm_vidc_alloc *alloc;
-		struct msm_vidc_map *map;
-
-		if (!buffers->size) {
-			s_vpr_e(inst->sid, "%s: invalid buffer %#x\n",
-				__func__, buffer_type);
-			return -EINVAL;
-		}
-		buffer = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
-		if (!buffer) {
-			s_vpr_e(inst->sid, "%s: buf alloc failed\n", __func__);
-			return -ENOMEM;
-		}
-		INIT_LIST_HEAD(&buffer->list);
-		buffer->valid = true;
-		buffer->type = buffer_type;
-		buffer->index = i;
-		buffer->buffer_size = buffers->size;
-		list_add_tail(&buffer->list, &buffers->list);
-
-		alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
-		if (!alloc) {
-			s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
-			return -ENOMEM;
-		}
-		INIT_LIST_HEAD(&alloc->list);
-		alloc->type = buffer_type;
-		alloc->region = msm_vidc_get_buffer_region(inst,
-					buffer_type, __func__);
-		alloc->size = buffer->buffer_size;
-		rc = msm_vidc_memory_alloc(inst->core, alloc);
-		if (rc)
-			return -ENOMEM;
-		list_add_tail(&alloc->list, &allocations->list);
+	if (!buffers->size) {
+		s_vpr_e(inst->sid, "%s: invalid buffer %#x\n",
+			__func__, buffer_type);
+		return -EINVAL;
+	}
+	buffer = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
+	if (!buffer) {
+		s_vpr_e(inst->sid, "%s: buf alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(&buffer->list);
+	buffer->valid = true;
+	buffer->type = buffer_type;
+	buffer->index = index;
+	buffer->buffer_size = buffers->size;
+	list_add_tail(&buffer->list, &buffers->list);
 
-		map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
-		if (!map) {
-			s_vpr_e(inst->sid, "%s: map alloc failed\n", __func__);
-			return -ENOMEM;
-		}
-		INIT_LIST_HEAD(&map->list);
-		map->type = alloc->type;
-		map->region = alloc->region;
-		map->dmabuf = alloc->dmabuf;
-		rc = msm_vidc_memory_map(inst->core, map);
-		if (rc)
-			return -ENOMEM;
-		list_add_tail(&map->list, &mappings->list);
+	alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
+	if (!alloc) {
+		s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(&alloc->list);
+	alloc->type = buffer_type;
+	alloc->region = msm_vidc_get_buffer_region(inst,
+		buffer_type, __func__);
+	alloc->size = buffer->buffer_size;
+	rc = msm_vidc_memory_alloc(inst->core, alloc);
+	if (rc)
+		return -ENOMEM;
+	list_add_tail(&alloc->list, &allocations->list);
 
-		buffer->device_addr = map->device_addr;
-		s_vpr_h(inst->sid,
-			"%s: created buffer_type %#x, size %d device_addr %#x\n",
-			__func__, buffer_type, buffers->size,
-			buffer->device_addr);
+	map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
+	if (!map) {
+		s_vpr_e(inst->sid, "%s: map alloc failed\n", __func__);
+		return -ENOMEM;
 	}
+	INIT_LIST_HEAD(&map->list);
+	map->type = alloc->type;
+	map->region = alloc->region;
+	map->dmabuf = alloc->dmabuf;
+	rc = msm_vidc_memory_map(inst->core, map);
+	if (rc)
+		return -ENOMEM;
+	list_add_tail(&map->list, &mappings->list);
+
+	buffer->dmabuf = alloc->dmabuf;
+	buffer->device_addr = map->device_addr;
+	s_vpr_h(inst->sid,
+		"%s: created buffer_type %#x, size %d device_addr %#x\n",
+		__func__, buffer_type, buffers->size,
+		buffer->device_addr);
 
 	return 0;
 }
 
+int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
+		enum msm_vidc_buffer_type buffer_type)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	int i;
+
+	d_vpr_h("%s()\n", __func__);
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	for (i = 0; i < buffers->min_count; i++)
+		rc = msm_vidc_create_internal_buffer(inst, buffer_type, i);
+
+	return rc;
+}
+
 int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type)
 {

+ 261 - 0
driver/vidc/src/venus_hfi_response.c

@@ -8,6 +8,46 @@
 #include "venus_hfi_response.h"
 #include "msm_vidc_debug.h"
 #include "msm_vidc_driver.h"
+#include "msm_vdec.h"
+
+u32 vidc_port_from_hfi(struct msm_vidc_inst *inst,
+	enum hfi_packet_port_type hfi_port)
+{
+	enum msm_vidc_port_type port = MAX_PORT;
+
+	if (is_decode_session(inst)) {
+		switch (hfi_port) {
+		case HFI_PORT_BITSTREAM:
+			port = INPUT_PORT;
+			break;
+		case HFI_PORT_RAW:
+			port = OUTPUT_PORT;
+			break;
+		default:
+			s_vpr_e(inst->sid, "%s: invalid hfi port type %d\n",
+				__func__, hfi_port);
+			break;
+		}
+	} else if (is_encode_session(inst)) {
+		switch (hfi_port) {
+		case HFI_PORT_RAW:
+			port = INPUT_PORT;
+			break;
+		case HFI_PORT_BITSTREAM:
+			port = OUTPUT_PORT;
+			break;
+		default:
+			s_vpr_e(inst->sid, "%s: invalid hfi port type %d\n",
+				__func__, hfi_port);
+			break;
+		}
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid domain %#x\n",
+			__func__, inst->domain);
+	}
+
+	return port;
+}
 
 bool is_valid_hfi_port(struct msm_vidc_inst *inst, u32 port,
 	const char *func)
@@ -426,6 +466,151 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
 	return rc;
 }
 
+static int handle_persist_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_PERSIST, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static int handle_line_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_LINE, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static int handle_non_comv_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_NON_COMV, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static int handle_comv_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_COMV, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static int handle_bin_buffer(struct msm_vidc_inst *inst,
+	struct hfi_buffer *buffer)
+{
+	int rc = 0;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_buffer *buf;
+	bool found;
+
+	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_BIN, __func__);
+	if (!buffers)
+		return -EINVAL;
+
+	found = false;
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->device_addr == buffer->base_address) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		rc = msm_vidc_destroy_internal_buffer(inst, buf);
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
+			__func__, buffer->index, buffer->base_address);
+		return -EINVAL;
+	}
+	return rc;
+}
+
 static int handle_session_buffer(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
@@ -470,6 +655,16 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 				rc = handle_input_metadata_buffer(inst, buffer);
 			else if (buf_type == HFI_BUFFER_BITSTREAM)
 				rc = handle_input_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_BIN)
+				rc = handle_bin_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_COMV)
+				rc = handle_comv_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_NON_COMV)
+				rc = handle_non_comv_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_LINE)
+				rc = handle_line_buffer(inst, buffer);
+			else if (buf_type == HFI_BUFFER_PERSIST)
+				rc = handle_persist_buffer(inst, buffer);
 		} else if (port_type == HFI_PORT_RAW) {
 			if (buf_type == HFI_BUFFER_METADATA)
 				rc = handle_output_metadata_buffer(inst, buffer);
@@ -552,7 +747,54 @@ static int handle_session_command(struct msm_vidc_inst *inst,
 static int handle_session_property(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
+	u32 port;
+	u32 *payload_ptr;
+
 	s_vpr_h(inst->sid, "%s: property type %#x\n", __func__, pkt->type);
+
+	port = vidc_port_from_hfi(inst, pkt->port);
+	payload_ptr = (u32 *)((u8 *)pkt + sizeof(struct hfi_packet));
+
+	switch (pkt->type) {
+	case HFI_PROP_BITSTREAM_RESOLUTION:
+		inst->subcr_params[port].bitstream_resolution = payload_ptr[0];
+		break;
+	case HFI_PROP_CROP_OFFSETS:
+		inst->subcr_params[port].crop_offsets =
+			(u64)payload_ptr[0] << 32 | payload_ptr[1];
+		break;
+	case HFI_PROP_LUMA_CHROMA_BIT_DEPTH:
+		inst->subcr_params[port].bit_depth = payload_ptr[0];
+		break;
+	case HFI_PROP_CABAC_SESSION:
+		inst->subcr_params[port].cabac = payload_ptr[0];
+		break;
+	case HFI_PROP_CODED_FRAMES:
+		inst->subcr_params[port].coded_frames = payload_ptr[0];
+		break;
+	case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
+		inst->subcr_params[port].fw_min_count = payload_ptr[0];
+		break;
+	case HFI_PROP_PIC_ORDER_CNT_TYPE:
+		inst->subcr_params[port].pic_order_cnt = payload_ptr[0];
+		break;
+	case HFI_PROP_SIGNAL_COLOR_INFO:
+		inst->subcr_params[port].color_info = payload_ptr[0];
+		break;
+	case HFI_PROP_PROFILE:
+		inst->subcr_params[port].profile = payload_ptr[0];
+		break;
+	case HFI_PROP_LEVEL:
+		inst->subcr_params[port].level = payload_ptr[0];
+		break;
+	case HFI_PROP_TIER:
+		inst->subcr_params[port].tier = payload_ptr[0];
+		break;
+	default:
+		s_vpr_e(inst->sid, "%s: invalid port settings property %#x\n",
+			__func__, pkt->type);
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -662,6 +904,8 @@ static int handle_session_response(struct msm_vidc_core *core,
 	}
 
 	mutex_lock(&inst->lock);
+	inst->hfi_cmd_type = 0;
+	inst->hfi_port = 0;
 	pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
 
 	for (i = 0; i < hdr->num_packets; i++) {
@@ -673,6 +917,15 @@ static int handle_session_response(struct msm_vidc_core *core,
 		packet = (struct hfi_packet *)pkt;
 		if (packet->type < HFI_CMD_END &&
 		    packet->type > HFI_CMD_BEGIN) {
+			if (inst->hfi_cmd_type || inst->hfi_port) {
+				s_vpr_e(inst->sid,
+					"%s: invalid cmd %d, port %d \n",
+					__func__, inst->hfi_cmd_type,
+					inst->hfi_port);
+				return -EINVAL;
+			}
+			inst->hfi_cmd_type = packet->type;
+			inst->hfi_port = packet->port;
 			rc = handle_session_command(inst, packet);
 		} else if (packet->type > HFI_PROP_BEGIN &&
 			   packet->type < HFI_PROP_END) {
@@ -688,6 +941,14 @@ static int handle_session_response(struct msm_vidc_core *core,
 		}
 		pkt += packet->size;
 	}
+
+	if (inst->hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
+		if (inst->hfi_port == HFI_PORT_BITSTREAM)
+			rc = msm_vdec_input_port_settings_change(inst);
+		else if (inst->hfi_port == HFI_PORT_RAW)
+			rc = msm_vdec_output_port_settings_change(inst);
+	}
+
 exit:
 	mutex_unlock(&inst->lock);
 	put_inst(inst);