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

video: driver: Add support to update buffer flags

Add support to added buf flags in dequeued buffers based
on HFI_PROP_NO_OUTPUT and HFI_PROP_PICTURE_TYPE property
values received from video fw.

Change-Id: Icf285ab7feb88daf8991705964ed0d3214c99870
Signed-off-by: Akshata Sahukar <[email protected]>
Akshata Sahukar 4 éve
szülő
commit
508102a802

+ 1 - 0
driver/vidc/inc/msm_vidc_inst.h

@@ -118,6 +118,7 @@ struct msm_vidc_inst {
 	bool                               subscribed_input_prop;
 	bool                               subscribed_output_prop;
 	struct msm_vidc_subscription_params       subcr_params[MAX_PORT];
+	struct msm_vidc_frame_properties   frame_prop;
 	struct msm_vidc_decode_batch       decode_batch;
 	struct msm_vidc_decode_vpp_delay   decode_vpp_delay;
 	struct msm_vidc_session_idle       session_idle;

+ 12 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -602,6 +602,18 @@ struct msm_vidc_subscription_params {
 	u32                    tier;
 };
 
+struct msm_vidc_frame_properties {
+	u32                    hfi_picture_type;
+	u32                    hfi_no_output;
+	u32                    hfi_cr;
+	u32                    hfi_cf;
+};
+
+struct msm_vidc_cmd_range {
+	u32 begin;
+	u32 end;
+};
+
 struct msm_vidc_decode_vpp_delay {
 	bool                   enable;
 	u32                    size;

+ 191 - 111
driver/vidc/src/venus_hfi_response.c

@@ -386,6 +386,40 @@ static int handle_session_drain(struct msm_vidc_inst *inst,
 	return 0;
 }
 
+static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
+{
+	u32 driver_flags = 0;
+
+	if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_IDR) {
+		driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
+	} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_P) {
+		driver_flags |= MSM_VIDC_BUF_FLAG_PFRAME;
+	} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_B) {
+		driver_flags |= MSM_VIDC_BUF_FLAG_BFRAME;
+	} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_I) {
+		if (inst->codec == MSM_VIDC_VP9)
+			driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
+	} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_CRA) {
+		driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
+	} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_BLA) {
+		driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
+	}
+
+	if (inst->capabilities->cap[META_BUF_TAG].value) {
+		if (inst->frame_prop.hfi_no_output &&
+			!(hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG))
+			driver_flags |= MSM_VIDC_BUF_FLAG_ERROR;
+	}
+
+	if (hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
+		driver_flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
+
+	if (hfi_flags & HFI_BUF_FW_FLAG_LAST)
+		driver_flags |= MSM_VIDC_BUF_FLAG_LAST;
+
+	return driver_flags;
+}
+
 static int handle_input_buffer(struct msm_vidc_inst *inst,
 	struct hfi_buffer *buffer)
 {
@@ -414,17 +448,9 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
 	buf->data_size = buffer->data_size;
 	buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
 	buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
+
 	buf->flags = 0;
-	//todo:
-	/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT) {
-		i_vpr_h(inst, "%s: data corrupted\n", __func__);
-		buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;
-	}
-	if (buffer->flags & HFI_BUF_FW_FLAG_UNSUPPORTED) {
-		i_vpr_e(inst, "%s: unsupported input\n", __func__);
-		buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;
-		// TODO: move inst->state to error state
-	}*/
+	buf->flags = get_driver_buffer_flags(inst, buffer->flags);
 
 	print_vidc_buffer(VIDC_HIGH, "EBD", inst, buf);
 	msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
@@ -467,21 +493,10 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	else
 		buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY;
 
+
 	buf->flags = 0;
-	//todo: moved to HFI_PROP_PICTURE_TYPE
-	/*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME)
-		buf->flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;*/
-	//moved to HFI_INFO_DATA_CORRUPT
-	/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT)
-		buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;*/
-	if (buffer->flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
-		buf->flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
-	//moved to HFI_PROP_SUBFRAME_OUTPUT
-	/*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
-		buf->flags |= MSM_VIDC_BUF_FLAG_SUBFRAME;*/
+	buf->flags = get_driver_buffer_flags(inst, buffer->flags);
 
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
-		buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
 	print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
 	msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
 
@@ -894,9 +909,26 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 static int handle_port_settings_change(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
+	int rc = 0;
+
 	i_vpr_h(inst, "%s: Received port settings change, type %d\n",
 		__func__, pkt->port);
-	return 0;
+
+	if (pkt->port == HFI_PORT_RAW) {
+		print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
+			inst->subcr_params[OUTPUT_PORT]);
+		rc = msm_vdec_output_port_settings_change(inst);
+	} else if (pkt->port == HFI_PORT_BITSTREAM) {
+		print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
+			inst->subcr_params[INPUT_PORT]);
+		rc = msm_vdec_input_port_settings_change(inst);
+	} else {
+		i_vpr_e(inst, "%s: invalid port type: %#x\n",
+			__func__, pkt->port);
+		rc = -EINVAL;
+	}
+
+	return rc;
 }
 
 static int handle_session_subscribe_mode(struct msm_vidc_inst *inst,
@@ -958,6 +990,7 @@ static int handle_session_command(struct msm_vidc_inst *inst,
 static int handle_session_property(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
+	int rc = 0;
 	u32 port;
 	u32 *payload_ptr;
 
@@ -998,12 +1031,33 @@ static int handle_session_property(struct msm_vidc_inst *inst,
 	case HFI_PROP_TIER:
 		inst->subcr_params[port].tier = payload_ptr[0];
 		break;
+	case HFI_PROP_PICTURE_TYPE:
+		if (is_encode_session(inst) && port == INPUT_PORT) {
+			rc = -EINVAL;
+			i_vpr_e(inst,
+				"%s: invalid port: %d for property %#x\n",
+				__func__, pkt->port, pkt->type);
+			break;
+		}
+		inst->frame_prop.hfi_picture_type = payload_ptr[0];
+		break;
+	case HFI_PROP_NO_OUTPUT:
+		if (port != INPUT_PORT) {
+			rc = -EINVAL;
+			i_vpr_e(inst,
+				"%s: invalid port: %d for property %#x\n",
+				__func__, pkt->port, pkt->type);
+			break;
+		}
+		inst->frame_prop.hfi_no_output = 1;
+		break;
 	default:
 		i_vpr_e(inst, "%s: invalid port settings property %#x\n",
 			__func__, pkt->type);
 		return -EINVAL;
 	}
-	return 0;
+
+	return rc;
 }
 
 static int handle_image_version_property(struct msm_vidc_core *core,
@@ -1096,16 +1150,48 @@ exit:
 	return rc;
 }
 
+static int process_response_packet(struct msm_vidc_inst *inst,
+		struct hfi_packet *packet)
+{
+	int rc = 0;
+
+	if (packet->type > HFI_CMD_BEGIN &&
+		packet->type < HFI_CMD_END) {
+		rc = handle_session_command(inst, packet);
+	} else if (packet->type > HFI_PROP_BEGIN &&
+		packet->type < HFI_PROP_END) {
+		rc = handle_session_property(inst, packet);
+	} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
+		packet->type < HFI_SESSION_ERROR_END) {
+		rc = handle_session_error(inst, packet);
+	} else if (packet->type > HFI_INFORMATION_BEGIN &&
+		packet->type < HFI_INFORMATION_END) {
+		rc = handle_session_info(inst, packet);
+	} else {
+		i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
+			__func__, packet->type);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
 int handle_session_response_work(struct msm_vidc_inst *inst,
 		struct response_work *resp_work)
 {
 	int rc = 0;
 	struct hfi_header *hdr = NULL;
 	struct hfi_packet *packet;
-	u8 *pkt, *temp_pkt;
+	u8 *pkt, *start_pkt;
 	u32 hfi_cmd_type = 0;
-	u32 hfi_port = 0;
-	int i;
+	int i, j;
+	struct msm_vidc_cmd_range be[5] = {
+		{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END},
+		{HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END},
+		{HFI_PROP_BEGIN, HFI_PROP_END},
+		{HFI_CMD_BEGIN, HFI_CMD_END},
+		{HFI_INFORMATION_BEGIN, HFI_INFORMATION_END},
+	};
 
 	if (!inst || !resp_work) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -1119,47 +1205,42 @@ int handle_session_response_work(struct msm_vidc_inst *inst,
 	}
 
 	hfi_cmd_type = 0;
-	hfi_port = 0;
 	pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
-	temp_pkt = pkt;
+	start_pkt = pkt;
 
+	/* validate all packets */
 	for (i = 0; i < hdr->num_packets; i++) {
+		packet = (struct hfi_packet * ) pkt;
 		if (validate_packet(pkt, resp_work->data,
 				resp_work->data_size, __func__)) {
 			rc = -EINVAL;
 			goto exit;
 		}
-		packet = (struct hfi_packet *)pkt;
-		if (packet->type > HFI_CMD_BEGIN &&
-			packet->type < HFI_CMD_END) {
-			if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
-				i_vpr_e(inst,
-					"%s: invalid packet type %d in port settings change\n",
-					__func__, packet->type);
-				rc = -EINVAL;
-				goto exit;
-			}
-			hfi_cmd_type = packet->type;
-			hfi_port = packet->port;
-			rc = handle_session_command(inst, packet);
-		} else if (packet->type > HFI_PROP_BEGIN &&
-			packet->type < HFI_PROP_END) {
-			rc = handle_session_property(inst, packet);
-		} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
-			packet->type < HFI_SESSION_ERROR_END) {
-			rc = handle_session_error(inst, packet);
-		} else if (packet->type > HFI_INFORMATION_BEGIN &&
-			packet->type < HFI_INFORMATION_END) {
-			rc = handle_session_info(inst, packet);
-		} else {
-			i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
-				__func__, packet->type);
-			rc = -EINVAL;
-			goto exit;
-		}
 		pkt += packet->size;
 	}
 
+	memset(&inst->frame_prop, 0,
+		sizeof(struct msm_vidc_frame_properties));
+	for (i = 0; i < ARRAY_SIZE(be); i++) {
+		pkt = start_pkt;
+		for (j = 0; j < hdr->num_packets; j++) {
+			packet = (struct hfi_packet * ) pkt;
+			if (packet->type > be[i].begin
+				&& packet->type < be[i].end) {
+				if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
+					i_vpr_e(inst,
+						"%s: invalid packet type %d in port settings change\n",
+						__func__, packet->type);
+					rc = -EINVAL;
+				}
+				hfi_cmd_type = packet->type;
+				rc = process_response_packet(inst, packet);
+				if (rc)
+					goto exit;
+			}
+			pkt += packet->size;
+		}
+	}
 
 	if (hfi_cmd_type == HFI_CMD_BUFFER) {
 		rc = handle_dequeue_buffers(inst);
@@ -1167,24 +1248,8 @@ int handle_session_response_work(struct msm_vidc_inst *inst,
 			goto exit;
 	}
 
-	if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
-		if (hfi_port == HFI_PORT_RAW) {
-			print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
-				inst->subcr_params[OUTPUT_PORT]);
-			rc = msm_vdec_output_port_settings_change(inst);
-			if (rc)
-				goto exit;
-		} else if (hfi_port == HFI_PORT_BITSTREAM) {
-			print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
-				inst->subcr_params[INPUT_PORT]);
-			rc = msm_vdec_input_port_settings_change(inst);
-			if (rc)
-				goto exit;
-		} else {
-			i_vpr_e(inst, "%s: invalid port type: %#x\n",
-				__func__, hfi_port);
-		}
-	}
+	memset(&inst->frame_prop, 0,
+		sizeof(struct msm_vidc_frame_properties));
 
 exit:
 	return rc;
@@ -1283,10 +1348,17 @@ static int handle_session_response(struct msm_vidc_core *core,
 	int rc = 0;
 	struct msm_vidc_inst *inst;
 	struct hfi_packet *packet;
-	u8 *pkt;
+	u8 *pkt, *start_pkt;
 	u32 hfi_cmd_type = 0;
 	u32 hfi_port = 0;
-	int i;
+	int i, j;
+	struct msm_vidc_cmd_range be[5] = {
+		{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END},
+		{HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END},
+		{HFI_PROP_BEGIN, HFI_PROP_END},
+		{HFI_CMD_BEGIN, HFI_CMD_END},
+		{HFI_INFORMATION_BEGIN, HFI_INFORMATION_END},
+	};
 
 	inst = get_inst(core, hdr->session_id);
 	if (!inst) {
@@ -1298,58 +1370,66 @@ static int handle_session_response(struct msm_vidc_core *core,
 	hfi_cmd_type = 0;
 	hfi_port = 0;
 	pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
+	start_pkt = pkt;
 
+	/* validate all packets */
 	for (i = 0; i < hdr->num_packets; i++) {
+		packet = (struct hfi_packet * ) pkt;
 		if (validate_packet(pkt, core->response_packet,
 				core->packet_size, __func__)) {
 			rc = -EINVAL;
 			goto exit;
 		}
-		packet = (struct hfi_packet *)pkt;
-		if (packet->type > HFI_CMD_BEGIN &&
-		    packet->type < HFI_CMD_END) {
-			if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
-				if (packet->port == HFI_PORT_BITSTREAM)
-					rc = queue_response_work(inst, RESP_WORK_INPUT_PSC,
-						(void *)hdr, hdr->size);
-				else if (packet->port == HFI_PORT_RAW)
-					rc = queue_response_work(inst, RESP_WORK_OUTPUT_PSC,
-						(void *)hdr, hdr->size);
-				goto exit;
-			} else if (packet->type == HFI_CMD_BUFFER &&
-						packet->port == HFI_PORT_RAW &&
-						check_last_flag(inst, packet)) {
-				rc = queue_response_work(inst, RESP_WORK_LAST_FLAG,
+		pkt += packet->size;
+	}
+
+	pkt = start_pkt;
+	for (j = 0; j < hdr->num_packets; j++) {
+		packet = (struct hfi_packet * ) pkt;
+		if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
+			if (packet->port == HFI_PORT_BITSTREAM)
+				rc = queue_response_work(inst,
+					RESP_WORK_INPUT_PSC,
+					(void *)hdr, hdr->size);
+			else if (packet->port == HFI_PORT_RAW)
+				rc = queue_response_work(inst,
+					RESP_WORK_OUTPUT_PSC,
 					(void *)hdr, hdr->size);
-				goto exit;
-			}
-			hfi_cmd_type = packet->type;
-			hfi_port = packet->port;
-			rc = handle_session_command(inst, packet);
-		} else if (packet->type > HFI_PROP_BEGIN &&
-			   packet->type < HFI_PROP_END) {
-			rc = handle_session_property(inst, packet);
-		} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
-			   packet->type < HFI_SESSION_ERROR_END) {
-			rc = handle_session_error(inst, packet);
-		} else if (packet->type > HFI_INFORMATION_BEGIN &&
-				packet->type < HFI_INFORMATION_END) {
-			rc = handle_session_info(inst, packet);
-		} else {
-			i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
-				__func__, packet->type);
-			rc = -EINVAL;
+			goto exit;
+		} else if (packet->type == HFI_CMD_BUFFER &&
+				packet->port == HFI_PORT_RAW &&
+				check_last_flag(inst, packet)) {
+			rc = queue_response_work(inst,
+				RESP_WORK_LAST_FLAG,
+				(void *)hdr, hdr->size);
 			goto exit;
 		}
 		pkt += packet->size;
 	}
 
+	memset(&inst->frame_prop, 0, sizeof(struct msm_vidc_frame_properties));
+	for (i = 0; i < ARRAY_SIZE(be); i++) {
+		pkt = start_pkt;
+		for (j = 0; j < hdr->num_packets; j++) {
+			packet = (struct hfi_packet * ) pkt;
+			if (packet->type > be[i].begin && packet->type < be[i].end) {
+				hfi_cmd_type = packet->type;
+				rc = process_response_packet(inst, packet);
+				if (rc)
+					goto exit;
+			}
+			pkt += packet->size;
+		}
+	}
+
 	if (hfi_cmd_type == HFI_CMD_BUFFER) {
 		rc = handle_dequeue_buffers(inst);
 		if (rc)
 			goto exit;
 	}
 
+	memset(&inst->frame_prop, 0, sizeof(struct msm_vidc_frame_properties));
+
 exit:
 	mutex_unlock(&inst->lock);
 	put_inst(inst);